Update FatFS library copies to the latest R0.09a version.

pull/1469/head
Dean Camera 12 years ago
parent 376160e2c0
commit c4aeb6d5ab

@ -1,4 +1,4 @@
FatFs Module Source Files R0.08b (C)ChaN, 2011
FatFs Module Source Files R0.09a (C)ChaN, 2012
FILES
@ -7,7 +7,8 @@ FILES
ff.h Common include file for FatFs and application module.
ff.c FatFs module.
diskio.h Common include file for FatFs and disk I/O module.
integer.h Alternative type definitions for integer variables.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
option Optional external functions.
Low level disk I/O module is not included in this archive because the FatFs
@ -23,7 +24,7 @@ AGREEMENTS
small embedded systems. This is a free software and is opened for education,
research and commercial developments under license policy of following trems.
Copyright (C) 2011, ChaN, all right reserved.
Copyright (C) 2012, ChaN, all right reserved.
* The FatFs module is a free software and there is NO WARRANTY.
* No restriction on use. You can use, modify and redistribute it for
@ -125,3 +126,10 @@ REVISION HISTORY
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf function.
Ignores duplicated directory separators in given path names.
Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
Added f_fdisk(). (_MULTI_PARTITION = 2)
Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16.
Changed API rejects null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.

@ -38,7 +38,7 @@ DRESULT disk_read (
BYTE drv, /* Physical drive number (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
BYTE count /* Number of sectors to read (1..128) */
)
{
DataflashManager_ReadBlocks_RAM(sector, count, buff);
@ -55,7 +55,7 @@ DRESULT disk_write (
BYTE drv, /* Physical drive number (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
BYTE count /* Number of sectors to write (1..128) */
)
{
DataflashManager_WriteBlocks_RAM(sector, count, buff);

@ -2,10 +2,12 @@
/ Low level disk interface module include file
/-----------------------------------------------------------------------*/
#ifndef _DISKIO
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#define _READONLY 0 /* 1: Read-only mode */
#define _USE_IOCTL 1
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h"
@ -45,23 +47,9 @@ DRESULT disk_ioctl (BYTE, BYTE, void*);
/* Generic command */
#define CTRL_SYNC 0 /* Mandatory for write functions */
#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */
#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */
#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */
#define CTRL_POWER 4
#define CTRL_LOCK 5
#define CTRL_EJECT 6
/* MMC/SDC command */
#define MMC_GET_TYPE 10
#define MMC_GET_CSD 11
#define MMC_GET_CID 12
#define MMC_GET_OCR 13
#define MMC_GET_SDSTAT 14
/* ATA/CF command */
#define ATA_GET_REV 20
#define ATA_GET_MODEL 21
#define ATA_GET_SN 22
#define _DISKIO
#ifdef __cplusplus
}
#endif
#endif

@ -1,11 +1,11 @@
/*----------------------------------------------------------------------------/
/ FatFs - FAT file system module R0.08b (C)ChaN, 2011
/ FatFs - FAT file system module R0.09a (C)ChaN, 2012
/-----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2011, ChaN, all right reserved.
/ Copyright (C) 2012, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
@ -86,7 +86,13 @@
/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
/ f_lseek() reports required table size on creating CLMP.
/ Extended format syntax of f_printf function.
/ Ignores duplicated directory separators in given path names.
/ Ignores duplicated directory separators in given path name.
/
/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
/ Added f_fdisk(). (_MULTI_PARTITION = 2)
/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
/ Changed f_open() and f_opendir reject null object pointer to avoid crash.
/ Changed option name _FS_SHARE to _FS_LOCK.
/---------------------------------------------------------------------------*/
#include "ff.h" /* FatFs configurations and declarations */
@ -99,7 +105,7 @@
---------------------------------------------------------------------------*/
#if _FATFS != 8237
#if _FATFS != 4004 /* Revision ID */
#error Wrong include file (ff.h).
#endif
@ -109,7 +115,7 @@
#error Wrong sector size.
#endif
#if _MAX_SS != 512
#define SS(fs) ((fs)->ssize) /* Multiple sector size */
#define SS(fs) ((fs)->ssize) /* Variable sector size */
#else
#define SS(fs) 512U /* Fixed sector size */
#endif
@ -130,10 +136,10 @@
#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
/* File sharing feature */
#if _FS_SHARE
/* File access control feature */
#if _FS_LOCK
#if _FS_READONLY
#error _FS_SHARE must be 0 on read-only cfg.
#error _FS_LOCK must be 0 on read-only cfg.
#endif
typedef struct {
FATFS *fs; /* File ID 1, volume (NULL:blank entry) */
@ -144,10 +150,6 @@ typedef struct {
#endif
/* Misc definitions */
#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
/* DBCS code ranges and SBCS extend char conversion table */
@ -434,8 +436,10 @@ typedef struct {
#define DIR_Name 0 /* Short file name (11) */
#define DIR_Attr 11 /* Attribute (1) */
#define DIR_NTres 12 /* NT flag (1) */
#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */
#define DIR_CrtTime 14 /* Created time (2) */
#define DIR_CrtDate 16 /* Created date (2) */
#define DIR_LstAccDate 18 /* Last accessed date (2) */
#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */
#define DIR_WrtTime 22 /* Modified time (2) */
#define DIR_WrtDate 24 /* Modified date (2) */
@ -449,17 +453,22 @@ typedef struct {
#define SZ_DIR 32 /* Size of a directory entry */
#define LLE 0x40 /* Last long entry flag in LDIR_Ord */
#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */
#define NDDE 0x05 /* Replacement of a character collides with DDE */
#define NDDE 0x05 /* Replacement of the character collides with DDE */
/*------------------------------------------------------------*/
/* Work area */
/* Module private work area */
/*------------------------------------------------------------*/
/* Note that uninitialized variables with static duration are
/ zeroed/nulled at start-up. If not, the compiler or start-up
/ routine is out of ANSI-C standard.
*/
#if _VOLUMES
static
FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */
#else
#error Number of drives must not be 0.
#error Number of volumes must not be 0.
#endif
static
@ -470,28 +479,28 @@ static
BYTE CurrVol; /* Current drive */
#endif
#if _FS_SHARE
#if _FS_LOCK
static
FILESEM Files[_FS_SHARE]; /* File lock semaphores */
FILESEM Files[_FS_LOCK]; /* File lock semaphores */
#endif
#if _USE_LFN == 0 /* No LFN */
#if _USE_LFN == 0 /* No LFN feature */
#define DEF_NAMEBUF BYTE sfn[12]
#define INIT_BUF(dobj) (dobj).fn = sfn
#define FREE_BUF()
#elif _USE_LFN == 1 /* LFN with static LFN working buffer */
#elif _USE_LFN == 1 /* LFN feature with static working buffer */
static WCHAR LfnBuf[_MAX_LFN+1];
#define DEF_NAMEBUF BYTE sfn[12]
#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
#define FREE_BUF()
#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */
#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */
#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; }
#define FREE_BUF()
#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */
#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */
#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn
#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
@ -523,10 +532,10 @@ void mem_cpy (void* dst, const void* src, UINT cnt) {
const BYTE *s = (const BYTE*)src;
#if _WORD_ACCESS == 1
while (cnt >= sizeof(int)) {
while (cnt >= sizeof (int)) {
*(int*)d = *(int*)s;
d += sizeof(int); s += sizeof(int);
cnt -= sizeof(int);
d += sizeof (int); s += sizeof (int);
cnt -= sizeof (int);
}
#endif
while (cnt--)
@ -581,7 +590,8 @@ void unlock_fs (
FRESULT res /* Result code to be returned */
)
{
if (res != FR_NOT_ENABLED &&
if (fs &&
res != FR_NOT_ENABLED &&
res != FR_INVALID_DRIVE &&
res != FR_INVALID_OBJECT &&
res != FR_TIMEOUT) {
@ -593,9 +603,9 @@ void unlock_fs (
/*-----------------------------------------------------------------------*/
/* File shareing control functions */
/* File lock control functions */
/*-----------------------------------------------------------------------*/
#if _FS_SHARE
#if _FS_LOCK
static
FRESULT chk_lock ( /* Check if the file can be accessed */
@ -606,7 +616,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */
UINT i, be;
/* Search file semaphore table */
for (i = be = 0; i < _FS_SHARE; i++) {
for (i = be = 0; i < _FS_LOCK; i++) {
if (Files[i].fs) { /* Existing entry */
if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */
Files[i].clu == dj->sclust &&
@ -615,7 +625,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */
be++;
}
}
if (i == _FS_SHARE) /* The file is not opened */
if (i == _FS_LOCK) /* The file is not opened */
return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */
/* The file has been opened. Reject any open against writing file and all write mode open */
@ -624,14 +634,12 @@ FRESULT chk_lock ( /* Check if the file can be accessed */
static
int enq_lock ( /* Check if an entry is available for a new file */
FATFS* fs /* File system object */
)
int enq_lock (void) /* Check if an entry is available for a new file */
{
UINT i;
for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
return (i == _FS_SHARE) ? 0 : 1;
for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
return (i == _FS_LOCK) ? 0 : 1;
}
@ -644,15 +652,15 @@ UINT inc_lock ( /* Increment file open counter and returns its index (0:int erro
UINT i;
for (i = 0; i < _FS_SHARE; i++) { /* Find the file */
for (i = 0; i < _FS_LOCK; i++) { /* Find the file */
if (Files[i].fs == dj->fs &&
Files[i].clu == dj->sclust &&
Files[i].idx == dj->index) break;
}
if (i == _FS_SHARE) { /* Not opened. Register it as new. */
for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
if (i == _FS_SHARE) return 0; /* No space to register (int err) */
if (i == _FS_LOCK) { /* Not opened. Register it as new. */
for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
if (i == _FS_LOCK) return 0; /* No space to register (int err) */
Files[i].fs = dj->fs;
Files[i].clu = dj->sclust;
Files[i].idx = dj->index;
@ -676,7 +684,7 @@ FRESULT dec_lock ( /* Decrement file open counter */
FRESULT res;
if (--i < _FS_SHARE) {
if (--i < _FS_LOCK) {
n = Files[i].ctr;
if (n == 0x100) n = 0;
if (n) n--;
@ -697,7 +705,7 @@ void clear_lock ( /* Clear lock entries of the volume */
{
UINT i;
for (i = 0; i < _FS_SHARE; i++) {
for (i = 0; i < _FS_LOCK; i++) {
if (Files[i].fs == fs) Files[i].fs = 0;
}
}
@ -776,7 +784,7 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */
fs->fsi_flag = 0;
}
/* Make sure that no pending write process in the physical drive */
if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK)
if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
res = FR_DISK_ERR;
}
@ -819,7 +827,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status
BYTE *p;
if (clst < 2 || clst >= fs->n_fatent) /* Chack range */
if (clst < 2 || clst >= fs->n_fatent) /* Check range */
return 1;
switch (fs->fs_type) {
@ -870,7 +878,7 @@ FRESULT put_fat (
} else {
switch (fs->fs_type) {
case FS_FAT12 :
bc = clst; bc += bc / 2;
bc = (UINT)clst; bc += bc / 2;
res = move_window(fs, fs->fatbase + (bc / SS(fs)));
if (res != FR_OK) break;
p = &fs->win[bc % SS(fs)];
@ -924,7 +932,7 @@ FRESULT remove_chain (
FRESULT res;
DWORD nxt;
#if _USE_ERASE
DWORD scl = clst, ecl = clst, resion[2];
DWORD scl = clst, ecl = clst, rt[2];
#endif
if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
@ -944,12 +952,12 @@ FRESULT remove_chain (
fs->fsi_flag = 1;
}
#if _USE_ERASE
if (ecl + 1 == nxt) { /* Next cluster is contiguous */
if (ecl + 1 == nxt) { /* Is next cluster contiguous? */
ecl = nxt;
} else { /* End of contiguous clusters */
resion[0] = clust2sect(fs, scl); /* Start sector */
resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */
} else { /* End of contiguous clusters */
rt[0] = clust2sect(fs, scl); /* Start sector */
rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */
scl = ecl = nxt;
}
#endif
@ -1058,7 +1066,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
static
FRESULT dir_sdi (
DIR *dj, /* Pointer to directory object */
WORD idx /* Directory index number */
WORD idx /* Index of directory table */
)
{
DWORD clst;
@ -1100,7 +1108,7 @@ FRESULT dir_sdi (
/*-----------------------------------------------------------------------*/
/* Directory handling - Move directory index next */
/* Directory handling - Move directory table index next */
/*-----------------------------------------------------------------------*/
static
@ -1113,6 +1121,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
WORD i;
stretch = stretch; /* To suppress warning on read-only cfg. */
i = dj->index + 1;
if (!i || !dj->sect) /* Report EOT when index has reached 65535 */
return FR_NO_FILE;
@ -1166,6 +1175,40 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
/*-----------------------------------------------------------------------*/
/* Directory handling - Load/Store start cluster number */
/*-----------------------------------------------------------------------*/
static
DWORD ld_clust (
FATFS *fs, /* Pointer to the fs object */
BYTE *dir /* Pointer to the directory entry */
)
{
DWORD cl;
cl = LD_WORD(dir+DIR_FstClusLO);
if (fs->fs_type == FS_FAT32)
cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16;
return cl;
}
#if !_FS_READONLY
static
void st_clust (
BYTE *dir, /* Pointer to the directory entry */
DWORD cl /* Value to be set */
)
{
ST_WORD(dir+DIR_FstClusLO, cl);
ST_WORD(dir+DIR_FstClusHI, cl >> 16);
}
#endif
/*-----------------------------------------------------------------------*/
/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */
/*-----------------------------------------------------------------------*/
@ -1777,7 +1820,7 @@ FRESULT create_name (
if (c >= 0x80) { /* Extended char? */
b |= 3; /* Eliminate NT flag */
#ifdef _EXCVT
c = excvt[c-0x80]; /* Upper conversion (SBCS) */
c = excvt[c - 0x80]; /* Upper conversion (SBCS) */
#else
#if !_DF1S /* ASCII only cfg */
return FR_INVALID_NAME;
@ -1933,7 +1976,6 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
if ((UINT)*path < ' ') { /* Nul path means the start directory itself */
res = dir_sdi(dj, 0);
dj->dir = 0;
} else { /* Follow path */
for (;;) {
res = create_name(dj, &path); /* Get a segment */
@ -1941,7 +1983,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
res = dir_find(dj); /* Find it */
ns = *(dj->fn+NS);
if (res != FR_OK) { /* Failed to find the object */
if (res != FR_NO_FILE) break; /* Abort if any hard error occured */
if (res != FR_NO_FILE) break; /* Abort if any hard error occurred */
/* Object not found */
if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */
dj->sclust = 0; dj->dir = 0; /* It is the root dir */
@ -1957,7 +1999,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
res = FR_NO_PATH; break;
}
dj->sclust = LD_CLUST(dir);
dj->sclust = ld_clust(dj->fs, dir);
}
}
@ -1968,11 +2010,11 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
/*-----------------------------------------------------------------------*/
/* Load boot record and check if it is an FAT boot record */
/* Load a sector and check if it is an FAT Volume Boot Record */
/*-----------------------------------------------------------------------*/
static
BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */
BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */
FATFS *fs, /* File system object */
DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
)
@ -2001,10 +2043,10 @@ static
FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
const TCHAR **path, /* Pointer to pointer to the path name (drive number) */
FATFS **rfs, /* Pointer to pointer to the found file system object */
BYTE chk_wp /* !=0: Check media write protection for write access */
BYTE wmode /* !=0: Check write protection for write access */
)
{
BYTE fmt, b, *tbl;
BYTE fmt, b, pi, *tbl;
UINT vol;
DSTATUS stat;
DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
@ -2012,6 +2054,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
const TCHAR *p = *path;
FATFS *fs;
/* Get logical drive number from the path name */
vol = p[0] - '0'; /* Is there a drive number? */
if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */
@ -2024,55 +2067,56 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
#endif
}
/* Check if the logical drive is valid or not */
/* Check if the file system object is valid or not */
*rfs = 0;
if (vol >= _VOLUMES) /* Is the drive number valid? */
return FR_INVALID_DRIVE;
*rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */
fs = FatFs[vol]; /* Get corresponding file system object */
if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */
ENTER_FF(fs); /* Lock file system */
if (fs->fs_type) { /* If the logical drive has been mounted */
*rfs = fs; /* Return pointer to the corresponding file system object */
if (fs->fs_type) { /* If the volume has been mounted */
stat = disk_status(fs->drv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
#endif
return FR_OK; /* The file system object is valid */
}
}
/* The logical drive must be mounted. */
/* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */
/* The file system object is not valid. */
/* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */
fs->fs_type = 0; /* Clear the file system object */
fs->drv = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */
fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->drv); /* Initialize the physical drive */
if (stat & STA_NOINIT) /* Check if the initialization succeeded */
return FR_NOT_READY; /* Failed to initialize due to no media or hard error */
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */
return FR_WRITE_PROTECTED;
#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */
if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK)
return FR_DISK_ERR;
#endif
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */
return FR_WRITE_PROTECTED;
#endif
/* Search FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */
fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */
if (fmt == 1) { /* Not an FAT-VBR, the disk may be partitioned */
/* Check the partition listed in top of the partition table */
tbl = &fs->win[MBR_Table + LD2PT(vol) * SZ_PTE];/* Partition table */
if (tbl[4]) { /* Is the partition existing? */
bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */
fmt = check_fs(fs, bsect); /* Check the partition */
/* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */
fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */
if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */
if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */
/* Check the partition listed in the partition table */
pi = LD2PT(vol);
if (pi) pi--;
tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */
if (tbl[4]) { /* Is the partition existing? */
bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */
fmt = check_fs(fs, bsect); /* Check the partition */
}
}
if (fmt == 3) return FR_DISK_ERR;
if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */
if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */
/* Following code initializes the file system object */
/* An FAT volume is found. Following code initializes the file system object */
if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */
return FR_NO_FILESYSTEM;
@ -2148,7 +2192,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
#if _FS_RPATH
fs->cdir = 0; /* Current directory (root dir) */
#endif
#if _FS_SHARE /* Clear file lock semaphores */
#if _FS_LOCK /* Clear file lock semaphores */
clear_lock(fs);
#endif
@ -2164,16 +2208,19 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
static
FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
FATFS *fs, /* Pointer to the file system object */
WORD id /* Member id of the target object to be checked */
void* obj /* Pointer to the object FIL/DIR to check validity */
)
{
if (!fs || !fs->fs_type || fs->id != id)
FIL *fil;
fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */
if (!fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
return FR_INVALID_OBJECT;
ENTER_FF(fs); /* Lock file system */
ENTER_FF(fil->fs); /* Lock file system */
if (disk_status(fs->drv) & STA_NOINIT)
if (disk_status(fil->fs->drv) & STA_NOINIT)
return FR_NOT_READY;
return FR_OK;
@ -2202,27 +2249,27 @@ FRESULT f_mount (
FATFS *rfs;
if (vol >= _VOLUMES) /* Check if the drive number is valid */
if (vol >= _VOLUMES) /* Check if the drive number is valid */
return FR_INVALID_DRIVE;
rfs = FatFs[vol]; /* Get current fs object */
rfs = FatFs[vol]; /* Get current fs object */
if (rfs) {
#if _FS_SHARE
#if _FS_LOCK
clear_lock(rfs);
#endif
#if _FS_REENTRANT /* Discard sync object of the current volume */
#if _FS_REENTRANT /* Discard sync object of the current volume */
if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
#endif
rfs->fs_type = 0; /* Clear old fs object */
rfs->fs_type = 0; /* Clear old fs object */
}
if (fs) {
fs->fs_type = 0; /* Clear new fs object */
#if _FS_REENTRANT /* Create sync object for the new volume */
fs->fs_type = 0; /* Clear new fs object */
#if _FS_REENTRANT /* Create sync object for the new volume */
if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
#endif
}
FatFs[vol] = fs; /* Register new fs object */
FatFs[vol] = fs; /* Register new fs object */
return FR_OK;
}
@ -2246,6 +2293,7 @@ FRESULT f_open (
DEF_NAMEBUF;
if (!fp) return FR_INVALID_OBJECT;
fp->fs = 0; /* Clear file object */
#if !_FS_READONLY
@ -2255,103 +2303,104 @@ FRESULT f_open (
mode &= FA_READ;
res = chk_mounted(&path, &dj.fs, 0);
#endif
INIT_BUF(dj);
if (res == FR_OK)
if (res == FR_OK) {
INIT_BUF(dj);
res = follow_path(&dj, path); /* Follow the file path */
dir = dj.dir;
dir = dj.dir;
#if !_FS_READONLY /* R/W configuration */
if (res == FR_OK) {
if (!dir) /* Current dir itself */
res = FR_INVALID_NAME;
#if _FS_SHARE
else
res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
if (res == FR_OK) {
if (!dir) /* Current dir itself */
res = FR_INVALID_NAME;
#if _FS_LOCK
else
res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
#endif
}
/* Create or Open a file */
if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
DWORD dw, cl;
if (res != FR_OK) { /* No file, create new */
if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
#if _FS_SHARE
res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
}
/* Create or Open a file */
if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
DWORD dw, cl;
if (res != FR_OK) { /* No file, create new */
if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
#if _FS_LOCK
res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
#else
res = dir_register(&dj);
res = dir_register(&dj);
#endif
mode |= FA_CREATE_ALWAYS; /* File is created */
dir = dj.dir; /* New entry */
}
else { /* Any object is already existing */
if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
res = FR_DENIED;
} else {
if (mode & FA_CREATE_NEW) /* Cannot create as new file */
res = FR_EXIST;
mode |= FA_CREATE_ALWAYS; /* File is created */
dir = dj.dir; /* New entry */
}
}
if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
dw = get_fattime(); /* Created time */
ST_DWORD(dir+DIR_CrtTime, dw);
dir[DIR_Attr] = 0; /* Reset attribute */
ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */
cl = LD_CLUST(dir); /* Get start cluster */
ST_CLUST(dir, 0); /* cluster = 0 */
dj.fs->wflag = 1;
if (cl) { /* Remove the cluster chain if exist */
dw = dj.fs->winsect;
res = remove_chain(dj.fs, cl);
if (res == FR_OK) {
dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
res = move_window(dj.fs, dw);
else { /* Any object is already existing */
if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
res = FR_DENIED;
} else {
if (mode & FA_CREATE_NEW) /* Cannot create as new file */
res = FR_EXIST;
}
}
if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
dw = get_fattime(); /* Created time */
ST_DWORD(dir+DIR_CrtTime, dw);
dir[DIR_Attr] = 0; /* Reset attribute */
ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */
cl = ld_clust(dj.fs, dir); /* Get start cluster */
st_clust(dir, 0); /* cluster = 0 */
dj.fs->wflag = 1;
if (cl) { /* Remove the cluster chain if exist */
dw = dj.fs->winsect;
res = remove_chain(dj.fs, cl);
if (res == FR_OK) {
dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
res = move_window(dj.fs, dw);
}
}
}
}
}
else { /* Open an existing file */
if (res == FR_OK) { /* Follow succeeded */
if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
res = FR_NO_FILE;
} else {
if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
res = FR_DENIED;
else { /* Open an existing file */
if (res == FR_OK) { /* Follow succeeded */
if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
res = FR_NO_FILE;
} else {
if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
res = FR_DENIED;
}
}
}
}
if (res == FR_OK) {
if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */
mode |= FA__WRITTEN;
fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
fp->dir_ptr = dir;
#if _FS_SHARE
fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
if (!fp->lockid) res = FR_INT_ERR;
if (res == FR_OK) {
if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */
mode |= FA__WRITTEN;
fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
fp->dir_ptr = dir;
#if _FS_LOCK
fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
if (!fp->lockid) res = FR_INT_ERR;
#endif
}
}
#else /* R/O configuration */
if (res == FR_OK) { /* Follow succeeded */
if (!dir) { /* Current dir itself */
res = FR_INVALID_NAME;
} else {
if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
res = FR_NO_FILE;
if (res == FR_OK) { /* Follow succeeded */
dir = dj.dir;
if (!dir) { /* Current dir itself */
res = FR_INVALID_NAME;
} else {
if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
res = FR_NO_FILE;
}
}
}
#endif
FREE_BUF();
FREE_BUF();
if (res == FR_OK) {
fp->flag = mode; /* File access mode */
fp->sclust = LD_CLUST(dir); /* File start cluster */
fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */
fp->fptr = 0; /* File pointer */
fp->dsect = 0;
if (res == FR_OK) {
fp->flag = mode; /* File access mode */
fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */
fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */
fp->fptr = 0; /* File pointer */
fp->dsect = 0;
#if _USE_FASTSEEK
fp->cltbl = 0; /* Normal seek mode */
fp->cltbl = 0; /* Normal seek mode */
#endif
fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */
fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */
}
}
LEAVE_FF(dj.fs, res);
@ -2377,9 +2426,9 @@ FRESULT f_read (
BYTE csect, *rbuff = buff;
*br = 0; /* Initialize byte counter */
*br = 0; /* Clear read byte counter */
res = validate(fp->fs, fp->id); /* Check validity */
res = validate(fp); /* Check validity */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Aborted file? */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2443,7 +2492,7 @@ FRESULT f_read (
#endif
fp->dsect = sect;
}
rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
if (rcnt > btr) rcnt = btr;
#if _FS_TINY
if (move_window(fp->fs, fp->dsect)) /* Move sector window */
@ -2479,9 +2528,9 @@ FRESULT f_write (
BYTE csect;
*bw = 0; /* Initialize byte counter */
*bw = 0; /* Clear write byte counter */
res = validate(fp->fs, fp->id); /* Check validity */
res = validate(fp); /* Check validity */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Aborted file? */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2558,7 +2607,7 @@ FRESULT f_write (
#endif
fp->dsect = sect;
}
wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
if (wcnt > btw) wcnt = btw;
#if _FS_TINY
if (move_window(fp->fs, fp->dsect)) /* Move sector window */
@ -2593,7 +2642,7 @@ FRESULT f_sync (
BYTE *dir;
res = validate(fp->fs, fp->id); /* Check validity of the object */
res = validate(fp); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
#if !_FS_TINY /* Write-back dirty buffer */
@ -2609,9 +2658,10 @@ FRESULT f_sync (
dir = fp->dir_ptr;
dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */
ST_CLUST(dir, fp->sclust); /* Update start cluster */
st_clust(dir, fp->sclust); /* Update start cluster */
tim = get_fattime(); /* Update updated time */
ST_DWORD(dir+DIR_WrtTime, tim);
ST_WORD(dir+DIR_LstAccDate, 0);
fp->flag &= ~FA__WRITTEN;
fp->fs->wflag = 1;
res = sync(fp->fs);
@ -2637,21 +2687,26 @@ FRESULT f_close (
{
FRESULT res;
#if _FS_READONLY
FATFS *fs = fp->fs;
res = validate(fs, fp->id);
if (res == FR_OK) fp->fs = 0; /* Discard file object */
LEAVE_FF(fs, res);
#if _FS_READONLY
res = validate(fp);
{
#if _FS_REENTRANT
FATFS *fs = fp->fs;
#endif
if (res == FR_OK) fp->fs = 0; /* Discard file object */
LEAVE_FF(fs, res);
}
#else
res = f_sync(fp); /* Flush cached data */
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) { /* Decrement open counter */
#if _FS_REENTRANT
res = validate(fp->fs, fp->id);
FATFS *fs = fp->fs;;
res = validate(fp);
if (res == FR_OK) {
res = dec_lock(fp->lockid);
unlock_fs(fp->fs, FR_OK);
res = dec_lock(fp->lockid);
unlock_fs(fs, FR_OK);
}
#else
res = dec_lock(fp->lockid);
@ -2704,7 +2759,7 @@ FRESULT f_chdir (
dj.fs->cdir = dj.sclust; /* Start directory itself */
} else {
if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */
dj.fs->cdir = LD_CLUST(dj.dir);
dj.fs->cdir = ld_clust(dj.fs, dj.dir);
else
res = FR_NO_PATH; /* Reached but a file */
}
@ -2742,14 +2797,14 @@ FRESULT f_getcwd (
if (res != FR_OK) break;
res = dir_read(&dj);
if (res != FR_OK) break;
dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */
dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */
res = dir_sdi(&dj, 0);
if (res != FR_OK) break;
do { /* Find the entry links to the child dir */
res = dir_read(&dj);
if (res != FR_OK) break;
if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */
res = dir_next(&dj, 0);
if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */
res = dir_next(&dj, 0);
} while (res == FR_OK);
if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
if (res != FR_OK) break;
@ -2803,7 +2858,7 @@ FRESULT f_lseek (
FRESULT res;
res = validate(fp->fs, fp->id); /* Check validity of the object */
res = validate(fp); /* Check validity of the object */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Check abort flag */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2959,10 +3014,14 @@ FRESULT f_opendir (
)
{
FRESULT res;
FATFS *fs;
DEF_NAMEBUF;
if (!dj) return FR_INVALID_OBJECT;
res = chk_mounted(&path, &dj->fs, 0);
fs = dj->fs;
if (res == FR_OK) {
INIT_BUF(*dj);
res = follow_path(dj, path); /* Follow the path to the directory */
@ -2970,20 +3029,23 @@ FRESULT f_opendir (
if (res == FR_OK) { /* Follow completed */
if (dj->dir) { /* It is not the root dir */
if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */
dj->sclust = LD_CLUST(dj->dir);
dj->sclust = ld_clust(fs, dj->dir);
} else { /* The object is not a directory */
res = FR_NO_PATH;
}
}
if (res == FR_OK) {
dj->id = dj->fs->id;
dj->id = fs->id;
res = dir_sdi(dj, 0); /* Rewind dir */
}
}
if (res == FR_NO_FILE) res = FR_NO_PATH;
if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function faild */
} else {
dj->fs = 0;
}
LEAVE_FF(dj->fs, res);
LEAVE_FF(fs, res);
}
@ -3002,7 +3064,7 @@ FRESULT f_readdir (
DEF_NAMEBUF;
res = validate(dj->fs, dj->id); /* Check validity of the object */
res = validate(dj); /* Check validity of the object */
if (res == FR_OK) {
if (!fno) {
res = dir_sdi(dj, 0); /* Rewind the directory object */
@ -3075,6 +3137,7 @@ FRESULT f_getfree (
)
{
FRESULT res;
FATFS *fs;
DWORD n, clst, sect, stat;
UINT i;
BYTE fat, *p;
@ -3082,32 +3145,33 @@ FRESULT f_getfree (
/* Get drive number */
res = chk_mounted(&path, fatfs, 0);
fs = *fatfs;
if (res == FR_OK) {
/* If free_clust is valid, return it without full cluster scan */
if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) {
*nclst = (*fatfs)->free_clust;
if (fs->free_clust <= fs->n_fatent - 2) {
*nclst = fs->free_clust;
} else {
/* Get number of free clusters */
fat = (*fatfs)->fs_type;
fat = fs->fs_type;
n = 0;
if (fat == FS_FAT12) {
clst = 2;
do {
stat = get_fat(*fatfs, clst);
stat = get_fat(fs, clst);
if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
if (stat == 1) { res = FR_INT_ERR; break; }
if (stat == 0) n++;
} while (++clst < (*fatfs)->n_fatent);
} while (++clst < fs->n_fatent);
} else {
clst = (*fatfs)->n_fatent;
sect = (*fatfs)->fatbase;
clst = fs->n_fatent;
sect = fs->fatbase;
i = 0; p = 0;
do {
if (!i) {
res = move_window(*fatfs, sect++);
res = move_window(fs, sect++);
if (res != FR_OK) break;
p = (*fatfs)->win;
i = SS(*fatfs);
p = fs->win;
i = SS(fs);
}
if (fat == FS_FAT16) {
if (LD_WORD(p) == 0) n++;
@ -3118,12 +3182,12 @@ FRESULT f_getfree (
}
} while (--clst);
}
(*fatfs)->free_clust = n;
if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
fs->free_clust = n;
if (fat == FS_FAT32) fs->fsi_flag = 1;
*nclst = n;
}
}
LEAVE_FF(*fatfs, res);
LEAVE_FF(fs, res);
}
@ -3141,7 +3205,9 @@ FRESULT f_truncate (
DWORD ncl;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (!fp) return FR_INVALID_OBJECT;
res = validate(fp); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__ERROR) { /* Check abort flag */
res = FR_INT_ERR;
@ -3198,7 +3264,7 @@ FRESULT f_unlink (
res = follow_path(&dj, path); /* Follow the file path */
if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
res = FR_INVALID_NAME; /* Cannot remove dot entry */
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */
#endif
if (res == FR_OK) { /* The object is accessible */
@ -3209,19 +3275,19 @@ FRESULT f_unlink (
if (dir[DIR_Attr] & AM_RDO)
res = FR_DENIED; /* Cannot remove R/O object */
}
dclst = LD_CLUST(dir);
dclst = ld_clust(dj.fs, dir);
if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */
if (dclst < 2) {
res = FR_INT_ERR;
} else {
mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */
mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */
sdj.sclust = dclst;
res = dir_sdi(&sdj, 2); /* Exclude dot entries */
if (res == FR_OK) {
res = dir_read(&sdj);
if (res == FR_OK /* Not empty dir */
if (res == FR_OK /* Not empty dir */
#if _FS_RPATH
|| dclst == sdj.fs->cdir /* Current dir */
|| dclst == dj.fs->cdir /* Current dir */
#endif
) res = FR_DENIED;
if (res == FR_NO_FILE) res = FR_OK; /* Empty */
@ -3283,12 +3349,12 @@ FRESULT f_mkdir (
dir[DIR_Name] = '.';
dir[DIR_Attr] = AM_DIR;
ST_DWORD(dir+DIR_WrtTime, tim);
ST_CLUST(dir, dcl);
st_clust(dir, dcl);
mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */
dir[33] = '.'; pcl = dj.sclust;
if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
pcl = 0;
ST_CLUST(dir+SZ_DIR, pcl);
st_clust(dir+SZ_DIR, pcl);
for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */
dj.fs->winsect = dsc++;
dj.fs->wflag = 1;
@ -3304,7 +3370,7 @@ FRESULT f_mkdir (
dir = dj.dir;
dir[DIR_Attr] = AM_DIR; /* Attribute */
ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */
ST_CLUST(dir, dcl); /* Table start cluster */
st_clust(dir, dcl); /* Table start cluster */
dj.fs->wflag = 1;
res = sync(dj.fs);
}
@ -3424,7 +3490,7 @@ FRESULT f_rename (
res = follow_path(&djo, path_old); /* Check old object */
if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
res = FR_INVALID_NAME;
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) res = chk_lock(&djo, 2);
#endif
if (res == FR_OK) { /* Old object is found */
@ -3432,11 +3498,11 @@ FRESULT f_rename (
res = FR_NO_FILE;
} else {
mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */
mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */
mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */
res = follow_path(&djn, path_new);
if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */
if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */
/* Start critical section that any interruption or error can cause cross-link */
/* Start critical section that an interruption or error can cause cross-link */
res = dir_register(&djn); /* Register the new entry */
if (res == FR_OK) {
dir = djn.dir; /* Copy object information except for name */
@ -3444,16 +3510,16 @@ FRESULT f_rename (
dir[DIR_Attr] = buf[0] | AM_ARC;
djo.fs->wflag = 1;
if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */
dw = clust2sect(djn.fs, LD_CLUST(dir));
dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
if (!dw) {
res = FR_INT_ERR;
} else {
res = move_window(djn.fs, dw);
dir = djn.fs->win+SZ_DIR; /* .. entry */
res = move_window(djo.fs, dw);
dir = djo.fs->win+SZ_DIR; /* .. entry */
if (res == FR_OK && dir[1] == '.') {
dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust;
ST_CLUST(dir, dw);
djn.fs->wflag = 1;
dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust;
st_clust(dir, dw);
djo.fs->wflag = 1;
}
}
}
@ -3497,9 +3563,11 @@ FRESULT f_forward (
BYTE csect;
*bf = 0; /* Initialize byte counter */
*bf = 0; /* Clear transfer byte counter */
if (!fp) return FR_INVALID_OBJECT;
res = validate(fp->fs, fp->id); /* Check validity of the object */
res = validate(fp); /* Check validity of the object */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Check error flag */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -3555,10 +3623,10 @@ FRESULT f_mkfs (
{
static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
BYTE fmt, md, *tbl;
BYTE fmt, md, sys, *tbl, pdrv, part;
DWORD n_clst, vs, n, wsect;
UINT i;
DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */
DWORD b_vol, b_fat, b_dir, b_data; /* LBA */
DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */
FATFS *fs;
DSTATUS stat;
@ -3566,25 +3634,39 @@ FRESULT f_mkfs (
/* Check mounted drive and clear work area */
if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
if (sfd > 1) return FR_INVALID_PARAMETER;
if (au & (au - 1)) return FR_INVALID_PARAMETER;
fs = FatFs[drv];
if (!fs) return FR_NOT_ENABLED;
fs->fs_type = 0;
drv = LD2PD(drv);
pdrv = LD2PD(drv); /* Physical drive */
part = LD2PT(drv); /* Partition (0:auto detect, 1-4:get from partition table)*/
/* Get disk statics */
stat = disk_initialize(drv);
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
#if _MAX_SS != 512 /* Get disk sector size */
if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK)
if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
return FR_DISK_ERR;
#endif
if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
return FR_DISK_ERR;
b_vol = (sfd) ? 0 : 63; /* Volume start sector */
n_vol -= b_vol;
if (au & (au - 1)) au = 0; /* Check validity of the AU size */
if (!au) { /* AU auto selection */
if (_MULTI_PARTITION && part) {
/* Get partition information from partition table in the MBR */
if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */
b_vol = LD_DWORD(tbl+8); /* Volume start sector */
n_vol = LD_DWORD(tbl+12); /* Volume size */
} else {
/* Create a partition in this function */
if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
return FR_DISK_ERR;
b_vol = (sfd) ? 0 : 63; /* Volume start sector */
n_vol -= b_vol; /* Volume size */
}
if (!au) { /* AU auto selection */
vs = n_vol / (2000 / (SS(fs) / 512));
for (i = 0; vs < vst[i]; i++) ;
au = cst[i];
@ -3593,7 +3675,7 @@ FRESULT f_mkfs (
if (au == 0) au = 1;
if (au > 128) au = 128;
/* Pre-compute number of clusters and FAT syb-type */
/* Pre-compute number of clusters and FAT sub-type */
n_clst = n_vol / au;
fmt = FS_FAT12;
if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
@ -3613,10 +3695,10 @@ FRESULT f_mkfs (
b_fat = b_vol + n_rsv; /* FAT area start sector */
b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */
b_data = b_dir + n_dir; /* Data area start sector */
if (n_vol < b_data + au) return FR_MKFS_ABORTED; /* Too small volume */
if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */
/* Align data start sector to erase block boundary (for flash memory media) */
if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */
n = (n - b_data) / N_FATS;
if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */
@ -3632,36 +3714,42 @@ FRESULT f_mkfs (
|| (fmt == FS_FAT32 && n_clst < MIN_FAT32))
return FR_MKFS_ABORTED;
/* Create partition table if required */
if (sfd) { /* No partition table (SFD) */
md = 0xF0;
} else { /* With partition table (FDISK) */
DWORD n_disk = b_vol + n_vol;
mem_set(fs->win, 0, SS(fs));
tbl = fs->win+MBR_Table;
ST_DWORD(tbl, 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); /* CHS saturated */
}
tbl[5] = 254;
if (fmt != FS_FAT32) /* System ID */
tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06;
else
tbl[4] = 0x0c;
ST_DWORD(tbl+8, 63); /* Partition start in LBA */
ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */
ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */
if (disk_write(drv, fs->win, 0, 1) != RES_OK) /* Put the MBR into first physical sector */
return FR_DISK_ERR;
switch (fmt) { /* Determine system ID for partition table */
case FS_FAT12: sys = 0x01; break;
case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break;
default: sys = 0x0C;
}
if (_MULTI_PARTITION && part) {
/* Update system ID in the partition table */
tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
tbl[4] = sys;
if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
md = 0xF8;
} else {
if (sfd) { /* No partition table (SFD) */
md = 0xF0;
} else { /* Create partition table (FDISK) */
mem_set(fs->win, 0, SS(fs));
tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */
tbl[1] = 1; /* Partition start head */
tbl[2] = 1; /* Partition start sector */
tbl[3] = 0; /* Partition start cylinder */
tbl[4] = sys; /* System type */
tbl[5] = 254; /* Partition end head */
n = (b_vol + n_vol) / 63 / 255;
tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */
tbl[7] = (BYTE)n; /* End cylinder */
ST_DWORD(tbl+8, 63); /* Partition start in LBA */
ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */
ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */
if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */
return FR_DISK_ERR;
md = 0xF8;
}
}
/* Create volume boot record */
/* Create BPB in the VBR */
tbl = fs->win; /* Clear sector */
mem_set(tbl, 0, SS(fs));
mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
@ -3699,10 +3787,10 @@ FRESULT f_mkfs (
mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
}
ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */
if (disk_write(drv, tbl, b_vol, 1) != RES_OK) /* Write VBR */
if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */
return FR_DISK_ERR;
if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */
disk_write(drv, tbl, b_vol + 6, 1);
disk_write(pdrv, tbl, b_vol + 6, 1);
/* Initialize FAT area */
wsect = b_fat;
@ -3718,11 +3806,11 @@ FRESULT f_mkfs (
ST_DWORD(tbl+4, 0xFFFFFFFF);
ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */
}
if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
return FR_DISK_ERR;
mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */
for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */
if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
return FR_DISK_ERR;
}
}
@ -3730,7 +3818,7 @@ FRESULT f_mkfs (
/* Initialize root directory */
i = (fmt == FS_FAT32) ? au : n_dir;
do {
if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
return FR_DISK_ERR;
} while (--i);
@ -3739,7 +3827,7 @@ FRESULT f_mkfs (
DWORD eb[2];
eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
disk_ioctl(drv, CTRL_ERASE_SECTOR, eb);
disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);
}
#endif
@ -3750,13 +3838,82 @@ FRESULT f_mkfs (
ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */
ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */
ST_WORD(tbl+BS_55AA, 0xAA55);
disk_write(drv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */
disk_write(drv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */
disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */
disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */
}
return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
}
#if _MULTI_PARTITION == 2
/*-----------------------------------------------------------------------*/
/* Divide Physical Drive */
/*-----------------------------------------------------------------------*/
FRESULT f_fdisk (
BYTE pdrv, /* Physical drive number */
const DWORD szt[], /* Pointer to the size table for each partitions */
void* work /* Pointer to the working buffer */
)
{
UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
DSTATUS stat;
DWORD sz_disk, sz_part, s_part;
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
/* Determine CHS in the table regardless of the drive geometry */
for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
if (n == 256) n--;
e_hd = n - 1;
sz_cyl = 63 * n;
tot_cyl = sz_disk / sz_cyl;
/* Create partition table */
mem_set(buf, 0, _MAX_SS);
p = buf + MBR_Table; b_cyl = 0;
for (i = 0; i < 4; i++, p += SZ_PTE) {
p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
if (!p_cyl) continue;
s_part = (DWORD)sz_cyl * b_cyl;
sz_part = (DWORD)sz_cyl * p_cyl;
if (i == 0) { /* Exclude first track of cylinder 0 */
s_hd = 1;
s_part += 63; sz_part -= 63;
} else {
s_hd = 0;
}
e_cyl = b_cyl + p_cyl - 1;
if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
/* Set partition table */
p[1] = s_hd; /* Start head */
p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */
p[3] = (BYTE)b_cyl; /* Start cylinder */
p[4] = 0x06; /* System type (temporary setting) */
p[5] = e_hd; /* End head */
p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */
p[7] = (BYTE)e_cyl; /* End cylinder */
ST_DWORD(p + 8, s_part); /* Start sector in LBA */
ST_DWORD(p + 12, sz_part); /* Partition size */
/* Next partition */
b_cyl += p_cyl;
}
ST_WORD(p, 0xAA55);
return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR;
/* Write it to the MBR */
return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK;
}
#endif /* _MULTI_PARTITION == 2 */
#endif /* _USE_MKFS && !_FS_READONLY */
@ -3894,7 +4051,7 @@ int f_printf (
UINT i, j, w;
ULONG v;
TCHAR c, d, s[16], *p;
int res, cc;
int res, chc, cc;
va_start(arp, str);
@ -3930,11 +4087,13 @@ int f_printf (
case 'S' : /* String */
p = va_arg(arp, TCHAR*);
for (j = 0; p[j]; j++) ;
res = 0;
while (!(f & 2) && j++ < w) res += (cc = f_putc(' ', fil));
res += (cc = f_puts(p, fil));
while (j++ < w) res += (cc = f_putc(' ', fil));
if (cc != EOF) cc = res;
chc = 0;
if (!(f & 2)) {
while (j++ < w) chc += (cc = f_putc(' ', fil));
}
chc += (cc = f_puts(p, fil));
while (j++ < w) chc += (cc = f_putc(' ', fil));
if (cc != EOF) cc = chc;
continue;
case 'C' : /* Character */
cc = f_putc((TCHAR)va_arg(arp, int), fil); continue;
@ -3945,14 +4104,14 @@ int f_printf (
case 'D' : /* Signed decimal */
case 'U' : /* Unsigned decimal */
r = 10; break;
case 'X' : /* Hexadecimal */
case 'X' : /* Hexdecimal */
r = 16; break;
default: /* Unknown type (pass-through) */
cc = f_putc(c, fil); continue;
}
/* Get an argument and put it in numeral */
v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int));
v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int));
if (d == 'D' && (v & 0x80000000)) {
v = 0 - v;
f |= 8;
@ -3962,7 +4121,7 @@ int f_printf (
d = (TCHAR)(v % r); v /= r;
if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
s[i++] = d + '0';
} while (v && i < sizeof(s) / sizeof(s[0]));
} while (v && i < sizeof s / sizeof s[0]);
if (f & 8) s[i++] = '-';
j = i; d = (f & 1) ? '0' : ' ';
res = 0;
@ -3978,4 +4137,3 @@ int f_printf (
#endif /* !_FS_READONLY */
#endif /* _USE_STRFUNC */

@ -1,11 +1,11 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.08b (C)ChaN, 2011
/ FatFs - FAT file system module include file R0.09a (C)ChaN, 2012
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2011, ChaN, all right reserved.
/ Copyright (C) 2012, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
@ -15,7 +15,7 @@
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 8237 /* Revision ID */
#define _FATFS 4004 /* Revision ID */
#ifdef __cplusplus
extern "C" {
@ -33,17 +33,17 @@ extern "C" {
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
typedef struct {
BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */
#define LD2PT(vol) 0 /* Always mounts the 1st partition */
#else /* Single partition configuration */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */
#endif
@ -84,7 +84,7 @@ typedef struct {
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != 512
WORD ssize; /* Bytes per sector (512,1024,2048,4096) */
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
@ -111,24 +111,24 @@ typedef struct {
/* File object structure (FIL) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
FATFS* fs; /* Pointer to the related file system object */
WORD id; /* File system mount ID of the related file system object */
BYTE flag; /* File status flags */
BYTE pad1;
DWORD fptr; /* File read/write pointer (0 on file open) */
DWORD fptr; /* File read/write pointer (0ed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0 when fsize==0) */
DWORD clust; /* Current cluster */
DWORD dsect; /* Current data sector */
DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
DWORD clust; /* Current cluster of fpter */
DWORD dsect; /* Current data sector of fpter */
#if !_FS_READONLY
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
BYTE* dir_ptr; /* Pointer to the directory entry in the window */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
#endif
#if _FS_SHARE
UINT lockid; /* File lock ID (index of file semaphore table) */
#if _FS_LOCK
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File data read/write buffer */
@ -176,24 +176,25 @@ typedef struct {
typedef enum {
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
FR_NOT_READY, /* (3) The physical drive cannot work */
FR_NO_FILE, /* (4) Could not find the file */
FR_NO_PATH, /* (5) Could not find the path */
FR_INVALID_NAME, /* (6) The path name format is invalid */
FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */
FR_EXIST, /* (8) Acces denied due to prohibited access */
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
FR_EXIST, /* (8) Access denied due to prohibited access */
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
@ -216,27 +217,28 @@ FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change time-stamp of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change times-tamp of the file/dir */
FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
FRESULT f_chdrive (BYTE); /* Change current drive */
FRESULT f_chdir (const TCHAR*); /* Change current directory */
FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */
int f_putc (TCHAR, FIL*); /* Put a character to the file */
int f_puts (const TCHAR*, FIL*); /* Put a string to the file */
int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
#ifndef EOF
#define EOF (-1)
#endif
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->fsize)
#ifndef EOF
#define EOF (-1)
#endif
@ -308,7 +310,7 @@ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek function */
/* Fast seek feature */
#define CREATE_LINKMAP 0xFFFFFFFF
@ -333,4 +335,3 @@ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
#endif
#endif /* _FATFS */

@ -1,5 +1,5 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.08b (C)ChaN, 2011
/ FatFs - FAT file system module configuration file R0.09a (C)ChaN, 2012
/----------------------------------------------------------------------------/
/
/ CAUTION! Do not forget to make clean the project after any changes to
@ -7,7 +7,7 @@
/
/----------------------------------------------------------------------------*/
#ifndef _FFCONF
#define _FFCONF 8237 /* Revision ID */
#define _FFCONF 4004 /* Revision ID */
/*---------------------------------------------------------------------------/
@ -36,7 +36,7 @@
/ 3: f_lseek is removed in addition to 2. */
#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */
#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
@ -137,7 +137,7 @@
/ and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */
#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */
#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */
/* When set to 0, each volume is bound to the same physical drive number and
/ it can mount only first primaly partition. When it is set to 1, each volume
/ is tied to the partitions listed in VolToPart[]. */
@ -163,7 +163,8 @@
/ When the byte order on the memory is big-endian or address miss-aligned word
/ access results incorrect behavior, the _WORD_ACCESS must be set to 0.
/ If it is not the case, the value can also be set to 1 to improve the
/ performance and code size. */
/ performance and code size.
*/
/* A header file that defines sync object types on the O/S, such as
@ -181,9 +182,9 @@
/ function must be added to the project. */
#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
defines how many files can be opened simultaneously. */
#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
/* To enable file lock control feature, set _FS_LOCK to 1 or greater.
The value defines how many files can be opened simultaneously. */
#endif /* _FFCONFIG */

@ -1,4 +1,4 @@
FatFs Module Source Files R0.08b (C)ChaN, 2011
FatFs Module Source Files R0.09a (C)ChaN, 2012
FILES
@ -7,7 +7,8 @@ FILES
ff.h Common include file for FatFs and application module.
ff.c FatFs module.
diskio.h Common include file for FatFs and disk I/O module.
integer.h Alternative type definitions for integer variables.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
option Optional external functions.
Low level disk I/O module is not included in this archive because the FatFs
@ -23,7 +24,7 @@ AGREEMENTS
small embedded systems. This is a free software and is opened for education,
research and commercial developments under license policy of following trems.
Copyright (C) 2011, ChaN, all right reserved.
Copyright (C) 2012, ChaN, all right reserved.
* The FatFs module is a free software and there is NO WARRANTY.
* No restriction on use. You can use, modify and redistribute it for
@ -125,3 +126,10 @@ REVISION HISTORY
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf function.
Ignores duplicated directory separators in given path names.
Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
Added f_fdisk(). (_MULTI_PARTITION = 2)
Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16.
Changed API rejects null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.

@ -38,7 +38,7 @@ DRESULT disk_read (
BYTE drv, /* Physical drive number (0..) */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to read (1..255) */
BYTE count /* Number of sectors to read (1..128) */
)
{
DataflashManager_ReadBlocks_RAM(sector, count, buff);
@ -55,7 +55,7 @@ DRESULT disk_write (
BYTE drv, /* Physical drive number (0..) */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address (LBA) */
BYTE count /* Number of sectors to write (1..255) */
BYTE count /* Number of sectors to write (1..128) */
)
{
DataflashManager_WriteBlocks_RAM(sector, count, buff);

@ -2,10 +2,12 @@
/ Low level disk interface module include file
/-----------------------------------------------------------------------*/
#ifndef _DISKIO
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#define _READONLY 0 /* 1: Read-only mode */
#define _USE_IOCTL 0
#ifdef __cplusplus
extern "C" {
#endif
#include "integer.h"
#include "ff.h"
@ -32,9 +34,7 @@ typedef enum {
DSTATUS disk_initialize (BYTE);
DSTATUS disk_status (BYTE);
DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
#if _READONLY == 0
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
#endif
DRESULT disk_ioctl (BYTE, BYTE, void*);
@ -45,6 +45,8 @@ DRESULT disk_ioctl (BYTE, BYTE, void*);
#define STA_PROTECT 0x04 /* Write protected */
#define _DISKIO
#ifdef __cplusplus
}
#endif
#endif

@ -1,11 +1,11 @@
/*----------------------------------------------------------------------------/
/ FatFs - FAT file system module R0.08b (C)ChaN, 2011
/ FatFs - FAT file system module R0.09a (C)ChaN, 2012
/-----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2011, ChaN, all right reserved.
/ Copyright (C) 2012, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
@ -86,7 +86,13 @@
/ Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
/ f_lseek() reports required table size on creating CLMP.
/ Extended format syntax of f_printf function.
/ Ignores duplicated directory separators in given path names.
/ Ignores duplicated directory separators in given path name.
/
/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
/ Added f_fdisk(). (_MULTI_PARTITION = 2)
/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
/ Changed f_open() and f_opendir reject null object pointer to avoid crash.
/ Changed option name _FS_SHARE to _FS_LOCK.
/---------------------------------------------------------------------------*/
#include "ff.h" /* FatFs configurations and declarations */
@ -99,7 +105,7 @@
---------------------------------------------------------------------------*/
#if _FATFS != 8237
#if _FATFS != 4004 /* Revision ID */
#error Wrong include file (ff.h).
#endif
@ -109,7 +115,7 @@
#error Wrong sector size.
#endif
#if _MAX_SS != 512
#define SS(fs) ((fs)->ssize) /* Multiple sector size */
#define SS(fs) ((fs)->ssize) /* Variable sector size */
#else
#define SS(fs) 512U /* Fixed sector size */
#endif
@ -130,10 +136,10 @@
#define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
/* File sharing feature */
#if _FS_SHARE
/* File access control feature */
#if _FS_LOCK
#if _FS_READONLY
#error _FS_SHARE must be 0 on read-only cfg.
#error _FS_LOCK must be 0 on read-only cfg.
#endif
typedef struct {
FATFS *fs; /* File ID 1, volume (NULL:blank entry) */
@ -144,10 +150,6 @@ typedef struct {
#endif
/* Misc definitions */
#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
/* DBCS code ranges and SBCS extend char conversion table */
@ -434,8 +436,10 @@ typedef struct {
#define DIR_Name 0 /* Short file name (11) */
#define DIR_Attr 11 /* Attribute (1) */
#define DIR_NTres 12 /* NT flag (1) */
#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */
#define DIR_CrtTime 14 /* Created time (2) */
#define DIR_CrtDate 16 /* Created date (2) */
#define DIR_LstAccDate 18 /* Last accessed date (2) */
#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */
#define DIR_WrtTime 22 /* Modified time (2) */
#define DIR_WrtDate 24 /* Modified date (2) */
@ -449,17 +453,22 @@ typedef struct {
#define SZ_DIR 32 /* Size of a directory entry */
#define LLE 0x40 /* Last long entry flag in LDIR_Ord */
#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */
#define NDDE 0x05 /* Replacement of a character collides with DDE */
#define NDDE 0x05 /* Replacement of the character collides with DDE */
/*------------------------------------------------------------*/
/* Work area */
/* Module private work area */
/*------------------------------------------------------------*/
/* Note that uninitialized variables with static duration are
/ zeroed/nulled at start-up. If not, the compiler or start-up
/ routine is out of ANSI-C standard.
*/
#if _VOLUMES
static
FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */
#else
#error Number of drives must not be 0.
#error Number of volumes must not be 0.
#endif
static
@ -470,28 +479,28 @@ static
BYTE CurrVol; /* Current drive */
#endif
#if _FS_SHARE
#if _FS_LOCK
static
FILESEM Files[_FS_SHARE]; /* File lock semaphores */
FILESEM Files[_FS_LOCK]; /* File lock semaphores */
#endif
#if _USE_LFN == 0 /* No LFN */
#if _USE_LFN == 0 /* No LFN feature */
#define DEF_NAMEBUF BYTE sfn[12]
#define INIT_BUF(dobj) (dobj).fn = sfn
#define FREE_BUF()
#elif _USE_LFN == 1 /* LFN with static LFN working buffer */
#elif _USE_LFN == 1 /* LFN feature with static working buffer */
static WCHAR LfnBuf[_MAX_LFN+1];
#define DEF_NAMEBUF BYTE sfn[12]
#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
#define FREE_BUF()
#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */
#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */
#define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
#define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; }
#define FREE_BUF()
#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */
#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */
#define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn
#define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
@ -523,10 +532,10 @@ void mem_cpy (void* dst, const void* src, UINT cnt) {
const BYTE *s = (const BYTE*)src;
#if _WORD_ACCESS == 1
while (cnt >= sizeof(int)) {
while (cnt >= sizeof (int)) {
*(int*)d = *(int*)s;
d += sizeof(int); s += sizeof(int);
cnt -= sizeof(int);
d += sizeof (int); s += sizeof (int);
cnt -= sizeof (int);
}
#endif
while (cnt--)
@ -581,7 +590,8 @@ void unlock_fs (
FRESULT res /* Result code to be returned */
)
{
if (res != FR_NOT_ENABLED &&
if (fs &&
res != FR_NOT_ENABLED &&
res != FR_INVALID_DRIVE &&
res != FR_INVALID_OBJECT &&
res != FR_TIMEOUT) {
@ -593,9 +603,9 @@ void unlock_fs (
/*-----------------------------------------------------------------------*/
/* File sharing control functions */
/* File lock control functions */
/*-----------------------------------------------------------------------*/
#if _FS_SHARE
#if _FS_LOCK
static
FRESULT chk_lock ( /* Check if the file can be accessed */
@ -606,7 +616,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */
UINT i, be;
/* Search file semaphore table */
for (i = be = 0; i < _FS_SHARE; i++) {
for (i = be = 0; i < _FS_LOCK; i++) {
if (Files[i].fs) { /* Existing entry */
if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */
Files[i].clu == dj->sclust &&
@ -615,7 +625,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */
be++;
}
}
if (i == _FS_SHARE) /* The file is not opened */
if (i == _FS_LOCK) /* The file is not opened */
return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */
/* The file has been opened. Reject any open against writing file and all write mode open */
@ -624,14 +634,12 @@ FRESULT chk_lock ( /* Check if the file can be accessed */
static
int enq_lock ( /* Check if an entry is available for a new file */
FATFS* fs /* File system object */
)
int enq_lock (void) /* Check if an entry is available for a new file */
{
UINT i;
for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
return (i == _FS_SHARE) ? 0 : 1;
for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
return (i == _FS_LOCK) ? 0 : 1;
}
@ -644,15 +652,15 @@ UINT inc_lock ( /* Increment file open counter and returns its index (0:int erro
UINT i;
for (i = 0; i < _FS_SHARE; i++) { /* Find the file */
for (i = 0; i < _FS_LOCK; i++) { /* Find the file */
if (Files[i].fs == dj->fs &&
Files[i].clu == dj->sclust &&
Files[i].idx == dj->index) break;
}
if (i == _FS_SHARE) { /* Not opened. Register it as new. */
for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
if (i == _FS_SHARE) return 0; /* No space to register (int err) */
if (i == _FS_LOCK) { /* Not opened. Register it as new. */
for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
if (i == _FS_LOCK) return 0; /* No space to register (int err) */
Files[i].fs = dj->fs;
Files[i].clu = dj->sclust;
Files[i].idx = dj->index;
@ -676,7 +684,7 @@ FRESULT dec_lock ( /* Decrement file open counter */
FRESULT res;
if (--i < _FS_SHARE) {
if (--i < _FS_LOCK) {
n = Files[i].ctr;
if (n == 0x100) n = 0;
if (n) n--;
@ -697,7 +705,7 @@ void clear_lock ( /* Clear lock entries of the volume */
{
UINT i;
for (i = 0; i < _FS_SHARE; i++) {
for (i = 0; i < _FS_LOCK; i++) {
if (Files[i].fs == fs) Files[i].fs = 0;
}
}
@ -776,7 +784,7 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */
fs->fsi_flag = 0;
}
/* Make sure that no pending write process in the physical drive */
if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK)
if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
res = FR_DISK_ERR;
}
@ -870,7 +878,7 @@ FRESULT put_fat (
} else {
switch (fs->fs_type) {
case FS_FAT12 :
bc = clst; bc += bc / 2;
bc = (UINT)clst; bc += bc / 2;
res = move_window(fs, fs->fatbase + (bc / SS(fs)));
if (res != FR_OK) break;
p = &fs->win[bc % SS(fs)];
@ -924,7 +932,7 @@ FRESULT remove_chain (
FRESULT res;
DWORD nxt;
#if _USE_ERASE
DWORD scl = clst, ecl = clst, resion[2];
DWORD scl = clst, ecl = clst, rt[2];
#endif
if (clst < 2 || clst >= fs->n_fatent) { /* Check range */
@ -944,12 +952,12 @@ FRESULT remove_chain (
fs->fsi_flag = 1;
}
#if _USE_ERASE
if (ecl + 1 == nxt) { /* Next cluster is contiguous */
if (ecl + 1 == nxt) { /* Is next cluster contiguous? */
ecl = nxt;
} else { /* End of contiguous clusters */
resion[0] = clust2sect(fs, scl); /* Start sector */
resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */
} else { /* End of contiguous clusters */
rt[0] = clust2sect(fs, scl); /* Start sector */
rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */
disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */
scl = ecl = nxt;
}
#endif
@ -1040,7 +1048,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
tbl = fp->cltbl + 1; /* Top of CLMT */
cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */
for (;;) {
ncl = *tbl++; /* Number of clusters in the fragment */
ncl = *tbl++; /* Number of cluters in the fragment */
if (!ncl) return 0; /* End of table? (error) */
if (cl < ncl) break; /* In this fragment? */
cl -= ncl; tbl++; /* Next fragment */
@ -1058,7 +1066,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */
static
FRESULT dir_sdi (
DIR *dj, /* Pointer to directory object */
WORD idx /* Directory index number */
WORD idx /* Index of directory table */
)
{
DWORD clst;
@ -1100,7 +1108,7 @@ FRESULT dir_sdi (
/*-----------------------------------------------------------------------*/
/* Directory handling - Move directory index next */
/* Directory handling - Move directory table index next */
/*-----------------------------------------------------------------------*/
static
@ -1113,6 +1121,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
WORD i;
stretch = stretch; /* To suppress warning on read-only cfg. */
i = dj->index + 1;
if (!i || !dj->sect) /* Report EOT when index has reached 65535 */
return FR_NO_FILE;
@ -1166,6 +1175,40 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
/*-----------------------------------------------------------------------*/
/* Directory handling - Load/Store start cluster number */
/*-----------------------------------------------------------------------*/
static
DWORD ld_clust (
FATFS *fs, /* Pointer to the fs object */
BYTE *dir /* Pointer to the directory entry */
)
{
DWORD cl;
cl = LD_WORD(dir+DIR_FstClusLO);
if (fs->fs_type == FS_FAT32)
cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16;
return cl;
}
#if !_FS_READONLY
static
void st_clust (
BYTE *dir, /* Pointer to the directory entry */
DWORD cl /* Value to be set */
)
{
ST_WORD(dir+DIR_FstClusLO, cl);
ST_WORD(dir+DIR_FstClusHI, cl >> 16);
}
#endif
/*-----------------------------------------------------------------------*/
/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */
/*-----------------------------------------------------------------------*/
@ -1777,7 +1820,7 @@ FRESULT create_name (
if (c >= 0x80) { /* Extended char? */
b |= 3; /* Eliminate NT flag */
#ifdef _EXCVT
c = excvt[c-0x80]; /* Upper conversion (SBCS) */
c = excvt[c - 0x80]; /* Upper conversion (SBCS) */
#else
#if !_DF1S /* ASCII only cfg */
return FR_INVALID_NAME;
@ -1933,7 +1976,6 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
if ((UINT)*path < ' ') { /* Nul path means the start directory itself */
res = dir_sdi(dj, 0);
dj->dir = 0;
} else { /* Follow path */
for (;;) {
res = create_name(dj, &path); /* Get a segment */
@ -1957,7 +1999,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
res = FR_NO_PATH; break;
}
dj->sclust = LD_CLUST(dir);
dj->sclust = ld_clust(dj->fs, dir);
}
}
@ -1968,11 +2010,11 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
/*-----------------------------------------------------------------------*/
/* Load boot record and check if it is an FAT boot record */
/* Load a sector and check if it is an FAT Volume Boot Record */
/*-----------------------------------------------------------------------*/
static
BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */
BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */
FATFS *fs, /* File system object */
DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */
)
@ -2001,10 +2043,10 @@ static
FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
const TCHAR **path, /* Pointer to pointer to the path name (drive number) */
FATFS **rfs, /* Pointer to pointer to the found file system object */
BYTE chk_wp /* !=0: Check media write protection for write access */
BYTE wmode /* !=0: Check write protection for write access */
)
{
BYTE fmt, b, *tbl;
BYTE fmt, b, pi, *tbl;
UINT vol;
DSTATUS stat;
DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
@ -2012,6 +2054,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
const TCHAR *p = *path;
FATFS *fs;
/* Get logical drive number from the path name */
vol = p[0] - '0'; /* Is there a drive number? */
if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */
@ -2024,55 +2067,56 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
#endif
}
/* Check if the logical drive is valid or not */
/* Check if the file system object is valid or not */
*rfs = 0;
if (vol >= _VOLUMES) /* Is the drive number valid? */
return FR_INVALID_DRIVE;
*rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */
fs = FatFs[vol]; /* Get corresponding file system object */
if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */
ENTER_FF(fs); /* Lock file system */
if (fs->fs_type) { /* If the logical drive has been mounted */
*rfs = fs; /* Return pointer to the corresponding file system object */
if (fs->fs_type) { /* If the volume has been mounted */
stat = disk_status(fs->drv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */
if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */
return FR_WRITE_PROTECTED;
#endif
return FR_OK; /* The file system object is valid */
}
}
/* The logical drive must be mounted. */
/* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */
/* The file system object is not valid. */
/* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */
fs->fs_type = 0; /* Clear the file system object */
fs->drv = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */
fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->drv); /* Initialize the physical drive */
if (stat & STA_NOINIT) /* Check if the initialization succeeded */
return FR_NOT_READY; /* Failed to initialize due to no media or hard error */
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */
return FR_WRITE_PROTECTED;
#if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */
if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK)
return FR_DISK_ERR;
#endif
#if !_FS_READONLY
if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */
return FR_WRITE_PROTECTED;
#endif
/* Search FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */
fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */
if (fmt == 1) { /* Not an FAT-VBR, the disk may be partitioned */
/* Check the partition listed in top of the partition table */
tbl = &fs->win[MBR_Table + LD2PT(vol) * SZ_PTE];/* Partition table */
if (tbl[4]) { /* Is the partition existing? */
bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */
fmt = check_fs(fs, bsect); /* Check the partition */
/* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */
fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */
if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */
if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */
/* Check the partition listed in the partition table */
pi = LD2PT(vol);
if (pi) pi--;
tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */
if (tbl[4]) { /* Is the partition existing? */
bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */
fmt = check_fs(fs, bsect); /* Check the partition */
}
}
if (fmt == 3) return FR_DISK_ERR;
if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */
if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */
/* Following code initializes the file system object */
/* An FAT volume is found. Following code initializes the file system object */
if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */
return FR_NO_FILESYSTEM;
@ -2148,7 +2192,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
#if _FS_RPATH
fs->cdir = 0; /* Current directory (root dir) */
#endif
#if _FS_SHARE /* Clear file lock semaphores */
#if _FS_LOCK /* Clear file lock semaphores */
clear_lock(fs);
#endif
@ -2164,16 +2208,19 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */
static
FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */
FATFS *fs, /* Pointer to the file system object */
WORD id /* Member id of the target object to be checked */
void* obj /* Pointer to the object FIL/DIR to check validity */
)
{
if (!fs || !fs->fs_type || fs->id != id)
FIL *fil;
fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */
if (!fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
return FR_INVALID_OBJECT;
ENTER_FF(fs); /* Lock file system */
ENTER_FF(fil->fs); /* Lock file system */
if (disk_status(fs->drv) & STA_NOINIT)
if (disk_status(fil->fs->drv) & STA_NOINIT)
return FR_NOT_READY;
return FR_OK;
@ -2202,27 +2249,27 @@ FRESULT f_mount (
FATFS *rfs;
if (vol >= _VOLUMES) /* Check if the drive number is valid */
if (vol >= _VOLUMES) /* Check if the drive number is valid */
return FR_INVALID_DRIVE;
rfs = FatFs[vol]; /* Get current fs object */
rfs = FatFs[vol]; /* Get current fs object */
if (rfs) {
#if _FS_SHARE
#if _FS_LOCK
clear_lock(rfs);
#endif
#if _FS_REENTRANT /* Discard sync object of the current volume */
#if _FS_REENTRANT /* Discard sync object of the current volume */
if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
#endif
rfs->fs_type = 0; /* Clear old fs object */
rfs->fs_type = 0; /* Clear old fs object */
}
if (fs) {
fs->fs_type = 0; /* Clear new fs object */
#if _FS_REENTRANT /* Create sync object for the new volume */
fs->fs_type = 0; /* Clear new fs object */
#if _FS_REENTRANT /* Create sync object for the new volume */
if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
#endif
}
FatFs[vol] = fs; /* Register new fs object */
FatFs[vol] = fs; /* Register new fs object */
return FR_OK;
}
@ -2246,6 +2293,7 @@ FRESULT f_open (
DEF_NAMEBUF;
if (!fp) return FR_INVALID_OBJECT;
fp->fs = 0; /* Clear file object */
#if !_FS_READONLY
@ -2255,103 +2303,104 @@ FRESULT f_open (
mode &= FA_READ;
res = chk_mounted(&path, &dj.fs, 0);
#endif
INIT_BUF(dj);
if (res == FR_OK)
if (res == FR_OK) {
INIT_BUF(dj);
res = follow_path(&dj, path); /* Follow the file path */
dir = dj.dir;
dir = dj.dir;
#if !_FS_READONLY /* R/W configuration */
if (res == FR_OK) {
if (!dir) /* Current dir itself */
res = FR_INVALID_NAME;
#if _FS_SHARE
else
res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
if (res == FR_OK) {
if (!dir) /* Current dir itself */
res = FR_INVALID_NAME;
#if _FS_LOCK
else
res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
#endif
}
/* Create or Open a file */
if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
DWORD dw, cl;
if (res != FR_OK) { /* No file, create new */
if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
#if _FS_SHARE
res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
}
/* Create or Open a file */
if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
DWORD dw, cl;
if (res != FR_OK) { /* No file, create new */
if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
#if _FS_LOCK
res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
#else
res = dir_register(&dj);
res = dir_register(&dj);
#endif
mode |= FA_CREATE_ALWAYS; /* File is created */
dir = dj.dir; /* New entry */
}
else { /* Any object is already existing */
if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
res = FR_DENIED;
} else {
if (mode & FA_CREATE_NEW) /* Cannot create as new file */
res = FR_EXIST;
mode |= FA_CREATE_ALWAYS; /* File is created */
dir = dj.dir; /* New entry */
}
}
if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
dw = get_fattime(); /* Created time */
ST_DWORD(dir+DIR_CrtTime, dw);
dir[DIR_Attr] = 0; /* Reset attribute */
ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */
cl = LD_CLUST(dir); /* Get start cluster */
ST_CLUST(dir, 0); /* cluster = 0 */
dj.fs->wflag = 1;
if (cl) { /* Remove the cluster chain if exist */
dw = dj.fs->winsect;
res = remove_chain(dj.fs, cl);
if (res == FR_OK) {
dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
res = move_window(dj.fs, dw);
else { /* Any object is already existing */
if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
res = FR_DENIED;
} else {
if (mode & FA_CREATE_NEW) /* Cannot create as new file */
res = FR_EXIST;
}
}
if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
dw = get_fattime(); /* Created time */
ST_DWORD(dir+DIR_CrtTime, dw);
dir[DIR_Attr] = 0; /* Reset attribute */
ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */
cl = ld_clust(dj.fs, dir); /* Get start cluster */
st_clust(dir, 0); /* cluster = 0 */
dj.fs->wflag = 1;
if (cl) { /* Remove the cluster chain if exist */
dw = dj.fs->winsect;
res = remove_chain(dj.fs, cl);
if (res == FR_OK) {
dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
res = move_window(dj.fs, dw);
}
}
}
}
}
else { /* Open an existing file */
if (res == FR_OK) { /* Follow succeeded */
if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
res = FR_NO_FILE;
} else {
if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
res = FR_DENIED;
else { /* Open an existing file */
if (res == FR_OK) { /* Follow succeeded */
if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
res = FR_NO_FILE;
} else {
if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
res = FR_DENIED;
}
}
}
}
if (res == FR_OK) {
if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */
mode |= FA__WRITTEN;
fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
fp->dir_ptr = dir;
#if _FS_SHARE
fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
if (!fp->lockid) res = FR_INT_ERR;
if (res == FR_OK) {
if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */
mode |= FA__WRITTEN;
fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
fp->dir_ptr = dir;
#if _FS_LOCK
fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
if (!fp->lockid) res = FR_INT_ERR;
#endif
}
}
#else /* R/O configuration */
if (res == FR_OK) { /* Follow succeeded */
if (!dir) { /* Current dir itself */
res = FR_INVALID_NAME;
} else {
if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
res = FR_NO_FILE;
if (res == FR_OK) { /* Follow succeeded */
dir = dj.dir;
if (!dir) { /* Current dir itself */
res = FR_INVALID_NAME;
} else {
if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
res = FR_NO_FILE;
}
}
}
#endif
FREE_BUF();
FREE_BUF();
if (res == FR_OK) {
fp->flag = mode; /* File access mode */
fp->sclust = LD_CLUST(dir); /* File start cluster */
fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */
fp->fptr = 0; /* File pointer */
fp->dsect = 0;
if (res == FR_OK) {
fp->flag = mode; /* File access mode */
fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */
fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */
fp->fptr = 0; /* File pointer */
fp->dsect = 0;
#if _USE_FASTSEEK
fp->cltbl = 0; /* Normal seek mode */
fp->cltbl = 0; /* Normal seek mode */
#endif
fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */
fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */
}
}
LEAVE_FF(dj.fs, res);
@ -2377,9 +2426,9 @@ FRESULT f_read (
BYTE csect, *rbuff = buff;
*br = 0; /* Initialize byte counter */
*br = 0; /* Clear read byte counter */
res = validate(fp->fs, fp->id); /* Check validity */
res = validate(fp); /* Check validity */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Aborted file? */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2443,7 +2492,7 @@ FRESULT f_read (
#endif
fp->dsect = sect;
}
rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
if (rcnt > btr) rcnt = btr;
#if _FS_TINY
if (move_window(fp->fs, fp->dsect)) /* Move sector window */
@ -2479,9 +2528,9 @@ FRESULT f_write (
BYTE csect;
*bw = 0; /* Initialize byte counter */
*bw = 0; /* Clear write byte counter */
res = validate(fp->fs, fp->id); /* Check validity */
res = validate(fp); /* Check validity */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Aborted file? */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2558,7 +2607,7 @@ FRESULT f_write (
#endif
fp->dsect = sect;
}
wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
if (wcnt > btw) wcnt = btw;
#if _FS_TINY
if (move_window(fp->fs, fp->dsect)) /* Move sector window */
@ -2593,7 +2642,7 @@ FRESULT f_sync (
BYTE *dir;
res = validate(fp->fs, fp->id); /* Check validity of the object */
res = validate(fp); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__WRITTEN) { /* Has the file been written? */
#if !_FS_TINY /* Write-back dirty buffer */
@ -2609,9 +2658,10 @@ FRESULT f_sync (
dir = fp->dir_ptr;
dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */
ST_CLUST(dir, fp->sclust); /* Update start cluster */
st_clust(dir, fp->sclust); /* Update start cluster */
tim = get_fattime(); /* Update updated time */
ST_DWORD(dir+DIR_WrtTime, tim);
ST_WORD(dir+DIR_LstAccDate, 0);
fp->flag &= ~FA__WRITTEN;
fp->fs->wflag = 1;
res = sync(fp->fs);
@ -2637,21 +2687,26 @@ FRESULT f_close (
{
FRESULT res;
#if _FS_READONLY
FATFS *fs = fp->fs;
res = validate(fs, fp->id);
if (res == FR_OK) fp->fs = 0; /* Discard file object */
LEAVE_FF(fs, res);
#if _FS_READONLY
res = validate(fp);
{
#if _FS_REENTRANT
FATFS *fs = fp->fs;
#endif
if (res == FR_OK) fp->fs = 0; /* Discard file object */
LEAVE_FF(fs, res);
}
#else
res = f_sync(fp); /* Flush cached data */
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) { /* Decrement open counter */
#if _FS_REENTRANT
res = validate(fp->fs, fp->id);
FATFS *fs = fp->fs;;
res = validate(fp);
if (res == FR_OK) {
res = dec_lock(fp->lockid);
unlock_fs(fp->fs, FR_OK);
res = dec_lock(fp->lockid);
unlock_fs(fs, FR_OK);
}
#else
res = dec_lock(fp->lockid);
@ -2704,7 +2759,7 @@ FRESULT f_chdir (
dj.fs->cdir = dj.sclust; /* Start directory itself */
} else {
if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */
dj.fs->cdir = LD_CLUST(dj.dir);
dj.fs->cdir = ld_clust(dj.fs, dj.dir);
else
res = FR_NO_PATH; /* Reached but a file */
}
@ -2742,14 +2797,14 @@ FRESULT f_getcwd (
if (res != FR_OK) break;
res = dir_read(&dj);
if (res != FR_OK) break;
dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */
dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */
res = dir_sdi(&dj, 0);
if (res != FR_OK) break;
do { /* Find the entry links to the child dir */
res = dir_read(&dj);
if (res != FR_OK) break;
if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */
res = dir_next(&dj, 0);
if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */
res = dir_next(&dj, 0);
} while (res == FR_OK);
if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
if (res != FR_OK) break;
@ -2803,7 +2858,7 @@ FRESULT f_lseek (
FRESULT res;
res = validate(fp->fs, fp->id); /* Check validity of the object */
res = validate(fp); /* Check validity of the object */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Check abort flag */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -2959,10 +3014,14 @@ FRESULT f_opendir (
)
{
FRESULT res;
FATFS *fs;
DEF_NAMEBUF;
if (!dj) return FR_INVALID_OBJECT;
res = chk_mounted(&path, &dj->fs, 0);
fs = dj->fs;
if (res == FR_OK) {
INIT_BUF(*dj);
res = follow_path(dj, path); /* Follow the path to the directory */
@ -2970,20 +3029,23 @@ FRESULT f_opendir (
if (res == FR_OK) { /* Follow completed */
if (dj->dir) { /* It is not the root dir */
if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */
dj->sclust = LD_CLUST(dj->dir);
dj->sclust = ld_clust(fs, dj->dir);
} else { /* The object is not a directory */
res = FR_NO_PATH;
}
}
if (res == FR_OK) {
dj->id = dj->fs->id;
dj->id = fs->id;
res = dir_sdi(dj, 0); /* Rewind dir */
}
}
if (res == FR_NO_FILE) res = FR_NO_PATH;
if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function failed */
} else {
dj->fs = 0;
}
LEAVE_FF(dj->fs, res);
LEAVE_FF(fs, res);
}
@ -3002,7 +3064,7 @@ FRESULT f_readdir (
DEF_NAMEBUF;
res = validate(dj->fs, dj->id); /* Check validity of the object */
res = validate(dj); /* Check validity of the object */
if (res == FR_OK) {
if (!fno) {
res = dir_sdi(dj, 0); /* Rewind the directory object */
@ -3075,6 +3137,7 @@ FRESULT f_getfree (
)
{
FRESULT res;
FATFS *fs;
DWORD n, clst, sect, stat;
UINT i;
BYTE fat, *p;
@ -3082,32 +3145,33 @@ FRESULT f_getfree (
/* Get drive number */
res = chk_mounted(&path, fatfs, 0);
fs = *fatfs;
if (res == FR_OK) {
/* If free_clust is valid, return it without full cluster scan */
if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) {
*nclst = (*fatfs)->free_clust;
if (fs->free_clust <= fs->n_fatent - 2) {
*nclst = fs->free_clust;
} else {
/* Get number of free clusters */
fat = (*fatfs)->fs_type;
fat = fs->fs_type;
n = 0;
if (fat == FS_FAT12) {
clst = 2;
do {
stat = get_fat(*fatfs, clst);
stat = get_fat(fs, clst);
if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
if (stat == 1) { res = FR_INT_ERR; break; }
if (stat == 0) n++;
} while (++clst < (*fatfs)->n_fatent);
} while (++clst < fs->n_fatent);
} else {
clst = (*fatfs)->n_fatent;
sect = (*fatfs)->fatbase;
clst = fs->n_fatent;
sect = fs->fatbase;
i = 0; p = 0;
do {
if (!i) {
res = move_window(*fatfs, sect++);
res = move_window(fs, sect++);
if (res != FR_OK) break;
p = (*fatfs)->win;
i = SS(*fatfs);
p = fs->win;
i = SS(fs);
}
if (fat == FS_FAT16) {
if (LD_WORD(p) == 0) n++;
@ -3118,12 +3182,12 @@ FRESULT f_getfree (
}
} while (--clst);
}
(*fatfs)->free_clust = n;
if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
fs->free_clust = n;
if (fat == FS_FAT32) fs->fsi_flag = 1;
*nclst = n;
}
}
LEAVE_FF(*fatfs, res);
LEAVE_FF(fs, res);
}
@ -3141,7 +3205,9 @@ FRESULT f_truncate (
DWORD ncl;
res = validate(fp->fs, fp->id); /* Check validity of the object */
if (!fp) return FR_INVALID_OBJECT;
res = validate(fp); /* Check validity of the object */
if (res == FR_OK) {
if (fp->flag & FA__ERROR) { /* Check abort flag */
res = FR_INT_ERR;
@ -3198,7 +3264,7 @@ FRESULT f_unlink (
res = follow_path(&dj, path); /* Follow the file path */
if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
res = FR_INVALID_NAME; /* Cannot remove dot entry */
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */
#endif
if (res == FR_OK) { /* The object is accessible */
@ -3209,19 +3275,19 @@ FRESULT f_unlink (
if (dir[DIR_Attr] & AM_RDO)
res = FR_DENIED; /* Cannot remove R/O object */
}
dclst = LD_CLUST(dir);
dclst = ld_clust(dj.fs, dir);
if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */
if (dclst < 2) {
res = FR_INT_ERR;
} else {
mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */
mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */
sdj.sclust = dclst;
res = dir_sdi(&sdj, 2); /* Exclude dot entries */
if (res == FR_OK) {
res = dir_read(&sdj);
if (res == FR_OK /* Not empty dir */
if (res == FR_OK /* Not empty dir */
#if _FS_RPATH
|| dclst == sdj.fs->cdir /* Current dir */
|| dclst == dj.fs->cdir /* Current dir */
#endif
) res = FR_DENIED;
if (res == FR_NO_FILE) res = FR_OK; /* Empty */
@ -3283,12 +3349,12 @@ FRESULT f_mkdir (
dir[DIR_Name] = '.';
dir[DIR_Attr] = AM_DIR;
ST_DWORD(dir+DIR_WrtTime, tim);
ST_CLUST(dir, dcl);
st_clust(dir, dcl);
mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */
dir[33] = '.'; pcl = dj.sclust;
if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
pcl = 0;
ST_CLUST(dir+SZ_DIR, pcl);
st_clust(dir+SZ_DIR, pcl);
for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */
dj.fs->winsect = dsc++;
dj.fs->wflag = 1;
@ -3304,7 +3370,7 @@ FRESULT f_mkdir (
dir = dj.dir;
dir[DIR_Attr] = AM_DIR; /* Attribute */
ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */
ST_CLUST(dir, dcl); /* Table start cluster */
st_clust(dir, dcl); /* Table start cluster */
dj.fs->wflag = 1;
res = sync(dj.fs);
}
@ -3361,7 +3427,7 @@ FRESULT f_chmod (
/*-----------------------------------------------------------------------*/
/* Change Time-stamp */
/* Change Timestamp */
/*-----------------------------------------------------------------------*/
FRESULT f_utime (
@ -3424,7 +3490,7 @@ FRESULT f_rename (
res = follow_path(&djo, path_old); /* Check old object */
if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
res = FR_INVALID_NAME;
#if _FS_SHARE
#if _FS_LOCK
if (res == FR_OK) res = chk_lock(&djo, 2);
#endif
if (res == FR_OK) { /* Old object is found */
@ -3432,11 +3498,11 @@ FRESULT f_rename (
res = FR_NO_FILE;
} else {
mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */
mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */
mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */
res = follow_path(&djn, path_new);
if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */
if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */
/* Start critical section that any interruption or error can cause cross-link */
/* Start critical section that an interruption or error can cause cross-link */
res = dir_register(&djn); /* Register the new entry */
if (res == FR_OK) {
dir = djn.dir; /* Copy object information except for name */
@ -3444,16 +3510,16 @@ FRESULT f_rename (
dir[DIR_Attr] = buf[0] | AM_ARC;
djo.fs->wflag = 1;
if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */
dw = clust2sect(djn.fs, LD_CLUST(dir));
dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
if (!dw) {
res = FR_INT_ERR;
} else {
res = move_window(djn.fs, dw);
dir = djn.fs->win+SZ_DIR; /* .. entry */
res = move_window(djo.fs, dw);
dir = djo.fs->win+SZ_DIR; /* .. entry */
if (res == FR_OK && dir[1] == '.') {
dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust;
ST_CLUST(dir, dw);
djn.fs->wflag = 1;
dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust;
st_clust(dir, dw);
djo.fs->wflag = 1;
}
}
}
@ -3497,9 +3563,11 @@ FRESULT f_forward (
BYTE csect;
*bf = 0; /* Initialize byte counter */
*bf = 0; /* Clear transfer byte counter */
if (!fp) return FR_INVALID_OBJECT;
res = validate(fp->fs, fp->id); /* Check validity of the object */
res = validate(fp); /* Check validity of the object */
if (res != FR_OK) LEAVE_FF(fp->fs, res);
if (fp->flag & FA__ERROR) /* Check error flag */
LEAVE_FF(fp->fs, FR_INT_ERR);
@ -3555,10 +3623,10 @@ FRESULT f_mkfs (
{
static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
BYTE fmt, md, *tbl;
BYTE fmt, md, sys, *tbl, pdrv, part;
DWORD n_clst, vs, n, wsect;
UINT i;
DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */
DWORD b_vol, b_fat, b_dir, b_data; /* LBA */
DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */
FATFS *fs;
DSTATUS stat;
@ -3566,25 +3634,39 @@ FRESULT f_mkfs (
/* Check mounted drive and clear work area */
if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
if (sfd > 1) return FR_INVALID_PARAMETER;
if (au & (au - 1)) return FR_INVALID_PARAMETER;
fs = FatFs[drv];
if (!fs) return FR_NOT_ENABLED;
fs->fs_type = 0;
drv = LD2PD(drv);
pdrv = LD2PD(drv); /* Physical drive */
part = LD2PT(drv); /* Partition (0:auto detect, 1-4:get from partition table)*/
/* Get disk statics */
stat = disk_initialize(drv);
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
#if _MAX_SS != 512 /* Get disk sector size */
if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK)
if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
return FR_DISK_ERR;
#endif
if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
return FR_DISK_ERR;
b_vol = (sfd) ? 0 : 63; /* Volume start sector */
n_vol -= b_vol;
if (au & (au - 1)) au = 0; /* Check validity of the AU size */
if (!au) { /* AU auto selection */
if (_MULTI_PARTITION && part) {
/* Get partition information from partition table in the MBR */
if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */
b_vol = LD_DWORD(tbl+8); /* Volume start sector */
n_vol = LD_DWORD(tbl+12); /* Volume size */
} else {
/* Create a partition in this function */
if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
return FR_DISK_ERR;
b_vol = (sfd) ? 0 : 63; /* Volume start sector */
n_vol -= b_vol; /* Volume size */
}
if (!au) { /* AU auto selection */
vs = n_vol / (2000 / (SS(fs) / 512));
for (i = 0; vs < vst[i]; i++) ;
au = cst[i];
@ -3593,7 +3675,7 @@ FRESULT f_mkfs (
if (au == 0) au = 1;
if (au > 128) au = 128;
/* Pre-compute number of clusters and FAT syb-type */
/* Pre-compute number of clusters and FAT sub-type */
n_clst = n_vol / au;
fmt = FS_FAT12;
if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
@ -3613,10 +3695,10 @@ FRESULT f_mkfs (
b_fat = b_vol + n_rsv; /* FAT area start sector */
b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */
b_data = b_dir + n_dir; /* Data area start sector */
if (n_vol < b_data + au) return FR_MKFS_ABORTED; /* Too small volume */
if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */
/* Align data start sector to erase block boundary (for flash memory media) */
if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */
n = (n - b_data) / N_FATS;
if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */
@ -3632,36 +3714,42 @@ FRESULT f_mkfs (
|| (fmt == FS_FAT32 && n_clst < MIN_FAT32))
return FR_MKFS_ABORTED;
/* Create partition table if required */
if (sfd) { /* No partition table (SFD) */
md = 0xF0;
} else { /* With partition table (FDISK) */
DWORD n_disk = b_vol + n_vol;
mem_set(fs->win, 0, SS(fs));
tbl = fs->win+MBR_Table;
ST_DWORD(tbl, 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); /* CHS saturated */
}
tbl[5] = 254;
if (fmt != FS_FAT32) /* System ID */
tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06;
else
tbl[4] = 0x0c;
ST_DWORD(tbl+8, 63); /* Partition start in LBA */
ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */
ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */
if (disk_write(drv, fs->win, 0, 1) != RES_OK) /* Put the MBR into first physical sector */
return FR_DISK_ERR;
switch (fmt) { /* Determine system ID for partition table */
case FS_FAT12: sys = 0x01; break;
case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break;
default: sys = 0x0C;
}
if (_MULTI_PARTITION && part) {
/* Update system ID in the partition table */
tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
tbl[4] = sys;
if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
md = 0xF8;
} else {
if (sfd) { /* No partition table (SFD) */
md = 0xF0;
} else { /* Create partition table (FDISK) */
mem_set(fs->win, 0, SS(fs));
tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */
tbl[1] = 1; /* Partition start head */
tbl[2] = 1; /* Partition start sector */
tbl[3] = 0; /* Partition start cylinder */
tbl[4] = sys; /* System type */
tbl[5] = 254; /* Partition end head */
n = (b_vol + n_vol) / 63 / 255;
tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */
tbl[7] = (BYTE)n; /* End cylinder */
ST_DWORD(tbl+8, 63); /* Partition start in LBA */
ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */
ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */
if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */
return FR_DISK_ERR;
md = 0xF8;
}
}
/* Create volume boot record */
/* Create BPB in the VBR */
tbl = fs->win; /* Clear sector */
mem_set(tbl, 0, SS(fs));
mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
@ -3699,10 +3787,10 @@ FRESULT f_mkfs (
mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
}
ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */
if (disk_write(drv, tbl, b_vol, 1) != RES_OK) /* Write VBR */
if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */
return FR_DISK_ERR;
if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */
disk_write(drv, tbl, b_vol + 6, 1);
disk_write(pdrv, tbl, b_vol + 6, 1);
/* Initialize FAT area */
wsect = b_fat;
@ -3718,11 +3806,11 @@ FRESULT f_mkfs (
ST_DWORD(tbl+4, 0xFFFFFFFF);
ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */
}
if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
return FR_DISK_ERR;
mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */
for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */
if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
return FR_DISK_ERR;
}
}
@ -3730,7 +3818,7 @@ FRESULT f_mkfs (
/* Initialize root directory */
i = (fmt == FS_FAT32) ? au : n_dir;
do {
if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
return FR_DISK_ERR;
} while (--i);
@ -3739,7 +3827,7 @@ FRESULT f_mkfs (
DWORD eb[2];
eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
disk_ioctl(drv, CTRL_ERASE_SECTOR, eb);
disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);
}
#endif
@ -3750,13 +3838,82 @@ FRESULT f_mkfs (
ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */
ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */
ST_WORD(tbl+BS_55AA, 0xAA55);
disk_write(drv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */
disk_write(drv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */
disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */
disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */
}
return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
}
#if _MULTI_PARTITION == 2
/*-----------------------------------------------------------------------*/
/* Divide Physical Drive */
/*-----------------------------------------------------------------------*/
FRESULT f_fdisk (
BYTE pdrv, /* Physical drive number */
const DWORD szt[], /* Pointer to the size table for each partitions */
void* work /* Pointer to the working buffer */
)
{
UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
DSTATUS stat;
DWORD sz_disk, sz_part, s_part;
stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
/* Determine CHS in the table regardless of the drive geometry */
for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
if (n == 256) n--;
e_hd = n - 1;
sz_cyl = 63 * n;
tot_cyl = sz_disk / sz_cyl;
/* Create partition table */
mem_set(buf, 0, _MAX_SS);
p = buf + MBR_Table; b_cyl = 0;
for (i = 0; i < 4; i++, p += SZ_PTE) {
p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
if (!p_cyl) continue;
s_part = (DWORD)sz_cyl * b_cyl;
sz_part = (DWORD)sz_cyl * p_cyl;
if (i == 0) { /* Exclude first track of cylinder 0 */
s_hd = 1;
s_part += 63; sz_part -= 63;
} else {
s_hd = 0;
}
e_cyl = b_cyl + p_cyl - 1;
if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
/* Set partition table */
p[1] = s_hd; /* Start head */
p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */
p[3] = (BYTE)b_cyl; /* Start cylinder */
p[4] = 0x06; /* System type (temporary setting) */
p[5] = e_hd; /* End head */
p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */
p[7] = (BYTE)e_cyl; /* End cylinder */
ST_DWORD(p + 8, s_part); /* Start sector in LBA */
ST_DWORD(p + 12, sz_part); /* Partition size */
/* Next partition */
b_cyl += p_cyl;
}
ST_WORD(p, 0xAA55);
return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR;
/* Write it to the MBR */
return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK;
}
#endif /* _MULTI_PARTITION == 2 */
#endif /* _USE_MKFS && !_FS_READONLY */
@ -3894,7 +4051,7 @@ int f_printf (
UINT i, j, w;
ULONG v;
TCHAR c, d, s[16], *p;
int res, cc;
int res, chc, cc;
va_start(arp, str);
@ -3930,11 +4087,13 @@ int f_printf (
case 'S' : /* String */
p = va_arg(arp, TCHAR*);
for (j = 0; p[j]; j++) ;
res = 0;
while (!(f & 2) && j++ < w) res += (cc = f_putc(' ', fil));
res += (cc = f_puts(p, fil));
while (j++ < w) res += (cc = f_putc(' ', fil));
if (cc != EOF) cc = res;
chc = 0;
if (!(f & 2)) {
while (j++ < w) chc += (cc = f_putc(' ', fil));
}
chc += (cc = f_puts(p, fil));
while (j++ < w) chc += (cc = f_putc(' ', fil));
if (cc != EOF) cc = chc;
continue;
case 'C' : /* Character */
cc = f_putc((TCHAR)va_arg(arp, int), fil); continue;
@ -3945,14 +4104,14 @@ int f_printf (
case 'D' : /* Signed decimal */
case 'U' : /* Unsigned decimal */
r = 10; break;
case 'X' : /* Hexadecimal */
case 'X' : /* Hexdecimal */
r = 16; break;
default: /* Unknown type (passthrough) */
default: /* Unknown type (pass-through) */
cc = f_putc(c, fil); continue;
}
/* Get an argument and put it in numeral */
v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int));
v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int));
if (d == 'D' && (v & 0x80000000)) {
v = 0 - v;
f |= 8;
@ -3962,7 +4121,7 @@ int f_printf (
d = (TCHAR)(v % r); v /= r;
if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
s[i++] = d + '0';
} while (v && i < sizeof(s) / sizeof(s[0]));
} while (v && i < sizeof s / sizeof s[0]);
if (f & 8) s[i++] = '-';
j = i; d = (f & 1) ? '0' : ' ';
res = 0;
@ -3978,4 +4137,3 @@ int f_printf (
#endif /* !_FS_READONLY */
#endif /* _USE_STRFUNC */

@ -1,11 +1,11 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.08b (C)ChaN, 2011
/ FatFs - FAT file system module include file R0.09a (C)ChaN, 2012
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/
/ Copyright (C) 2011, ChaN, all right reserved.
/ Copyright (C) 2012, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
@ -15,7 +15,7 @@
/----------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 8237 /* Revision ID */
#define _FATFS 4004 /* Revision ID */
#ifdef __cplusplus
extern "C" {
@ -33,17 +33,17 @@ extern "C" {
/* Definitions of volume management */
#if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
typedef struct {
BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
#else /* Single partition configuration */
#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */
#define LD2PT(vol) 0 /* Always mounts the 1st partition */
#else /* Single partition configuration */
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */
#endif
@ -84,7 +84,7 @@ typedef struct {
WORD id; /* File system mount ID */
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
#if _MAX_SS != 512
WORD ssize; /* Bytes per sector (512,1024,2048,4096) */
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
#endif
#if _FS_REENTRANT
_SYNC_t sobj; /* Identifier of sync object */
@ -111,24 +111,24 @@ typedef struct {
/* File object structure (FIL) */
typedef struct {
FATFS* fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
FATFS* fs; /* Pointer to the related file system object */
WORD id; /* File system mount ID of the related file system object */
BYTE flag; /* File status flags */
BYTE pad1;
DWORD fptr; /* File read/write pointer (0 on file open) */
DWORD fptr; /* File read/write pointer (0ed on file open) */
DWORD fsize; /* File size */
DWORD sclust; /* File start cluster (0 when fsize==0) */
DWORD clust; /* Current cluster */
DWORD dsect; /* Current data sector */
DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
DWORD clust; /* Current cluster of fpter */
DWORD dsect; /* Current data sector of fpter */
#if !_FS_READONLY
DWORD dir_sect; /* Sector containing the directory entry */
BYTE* dir_ptr; /* Ponter to the directory entry in the window */
BYTE* dir_ptr; /* Pointer to the directory entry in the window */
#endif
#if _USE_FASTSEEK
DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */
#endif
#if _FS_SHARE
UINT lockid; /* File lock ID (index of file semaphore table) */
#if _FS_LOCK
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
#endif
#if !_FS_TINY
BYTE buf[_MAX_SS]; /* File data read/write buffer */
@ -188,12 +188,13 @@ typedef enum {
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
FR_NOT_ENABLED, /* (12) The volume has no work area */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
} FRESULT;
@ -216,27 +217,28 @@ FRESULT f_sync (FIL*); /* Flush cached data of a writing file */
FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */
FRESULT f_mkdir (const TCHAR*); /* Create a new directory */
FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change time-stamp of the file/dir */
FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change times-tamp of the file/dir */
FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
FRESULT f_chdrive (BYTE); /* Change current drive */
FRESULT f_chdir (const TCHAR*); /* Change current directory */
FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */
FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */
FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */
FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */
int f_putc (TCHAR, FIL*); /* Put a character to the file */
int f_puts (const TCHAR*, FIL*); /* Put a string to the file */
int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */
TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */
#ifndef EOF
#define EOF (-1)
#endif
#define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
#define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->fsize)
#ifndef EOF
#define EOF (-1)
#endif
@ -308,7 +310,7 @@ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
#define AM_MASK 0x3F /* Mask of defined bits */
/* Fast seek function */
/* Fast seek feature */
#define CREATE_LINKMAP 0xFFFFFFFF
@ -333,4 +335,3 @@ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */
#endif
#endif /* _FATFS */

@ -1,5 +1,5 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.08b (C)ChaN, 2011
/ FatFs - FAT file system module configuration file R0.09a (C)ChaN, 2012
/----------------------------------------------------------------------------/
/
/ CAUTION! Do not forget to make clean the project after any changes to
@ -7,7 +7,7 @@
/
/----------------------------------------------------------------------------*/
#ifndef _FFCONF
#define _FFCONF 8237 /* Revision ID */
#define _FFCONF 4004 /* Revision ID */
/*---------------------------------------------------------------------------/
@ -36,7 +36,7 @@
/ 3: f_lseek is removed in addition to 2. */
#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */
#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */
/* To enable string functions, set _USE_STRFUNC to 1 or 2. */
@ -137,7 +137,7 @@
/ and GET_SECTOR_SIZE command must be implemented to the disk_ioctl function. */
#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */
#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */
/* When set to 0, each volume is bound to the same physical drive number and
/ it can mount only first primary partition. When it is set to 1, each volume
/ is tied to the partitions listed in VolToPart[]. */
@ -181,9 +181,9 @@
/ function must be added to the project. */
#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */
/* To enable file sharing feature, set _FS_SHARE to 1 or greater. The value
defines how many files can be opened simultaneously. */
#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */
/* To enable file lock control feature, set _FS_LOCK to 1 or greater.
The value defines how many files can be opened simultaneously. */
#endif /* _FFCONFIG */

Loading…
Cancel
Save