image/svg+xml
Brteve's API for EveApps
Version 0.0.1
The reference document for common folder of EveApps project.
 
Loading...
Searching...
No Matches
ff.h File Reference
#include "ffconf.h"

Go to the source code of this file.

Data Structures

struct  FATFS
 
struct  FFOBJID
 
struct  FIL
 
struct  DIR
 
struct  FILINFO
 
struct  MKFS_PARM
 

Macros

#define FF_DEFINED   86631 /* Revision ID */
 
#define FF_INTDEF   1
 
#define _T(x)   x
 
#define _TEXT(x)   x
 
#define f_eof(fp)   ((int)((fp)->fptr == (fp)->obj.objsize))
 
#define f_error(fp)   ((fp)->err)
 
#define f_tell(fp)   ((fp)->fptr)
 
#define f_size(fp)   ((fp)->obj.objsize)
 
#define f_rewind(fp)   f_lseek((fp), 0)
 
#define f_rewinddir(dp)   f_readdir((dp), 0)
 
#define f_rmdir(path)   f_unlink(path)
 
#define f_unmount(path)   f_mount(0, path, 0)
 
#define FA_READ   0x01
 
#define FA_WRITE   0x02
 
#define FA_OPEN_EXISTING   0x00
 
#define FA_CREATE_NEW   0x04
 
#define FA_CREATE_ALWAYS   0x08
 
#define FA_OPEN_ALWAYS   0x10
 
#define FA_OPEN_APPEND   0x30
 
#define CREATE_LINKMAP   ((FSIZE_t)0 - 1)
 
#define FM_FAT   0x01
 
#define FM_FAT32   0x02
 
#define FM_EXFAT   0x04
 
#define FM_ANY   0x07
 
#define FM_SFD   0x08
 
#define FS_FAT12   1
 
#define FS_FAT16   2
 
#define FS_FAT32   3
 
#define FS_EXFAT   4
 
#define AM_RDO   0x01 /* Read only */
 
#define AM_HID   0x02 /* Hidden */
 
#define AM_SYS   0x04 /* System */
 
#define AM_DIR   0x10 /* Directory */
 
#define AM_ARC   0x20 /* Archive */
 

Typedefs

typedef unsigned int UINT
 
typedef unsigned char BYTE
 
typedef unsigned short WORD
 
typedef unsigned long DWORD
 
typedef WORD WCHAR
 
typedef DWORD FSIZE_t
 
typedef DWORD LBA_t
 
typedef char TCHAR
 

Enumerations

enum  FRESULT {
  FR_OK = 0 , FR_DISK_ERR , FR_INT_ERR , FR_NOT_READY ,
  FR_NO_FILE , FR_NO_PATH , FR_INVALID_NAME , FR_DENIED ,
  FR_EXIST , FR_INVALID_OBJECT , FR_WRITE_PROTECTED , FR_INVALID_DRIVE ,
  FR_NOT_ENABLED , FR_NO_FILESYSTEM , FR_MKFS_ABORTED , FR_TIMEOUT ,
  FR_LOCKED , FR_NOT_ENOUGH_CORE , FR_TOO_MANY_OPEN_FILES , FR_INVALID_PARAMETER
}
 

Functions

FRESULT f_open (FIL *fp, const TCHAR *path, BYTE mode)
 
FRESULT f_close (FIL *fp)
 
FRESULT f_read (FIL *fp, void *buff, UINT btr, UINT *br)
 
FRESULT f_write (FIL *fp, const void *buff, UINT btw, UINT *bw)
 
FRESULT f_lseek (FIL *fp, FSIZE_t ofs)
 
FRESULT f_truncate (FIL *fp)
 
FRESULT f_sync (FIL *fp)
 
FRESULT f_opendir (DIR *dp, const TCHAR *path)
 
FRESULT f_closedir (DIR *dp)
 
FRESULT f_readdir (DIR *dp, FILINFO *fno)
 
FRESULT f_findfirst (DIR *dp, FILINFO *fno, const TCHAR *path, const TCHAR *pattern)
 
FRESULT f_findnext (DIR *dp, FILINFO *fno)
 
FRESULT f_mkdir (const TCHAR *path)
 
FRESULT f_unlink (const TCHAR *path)
 
FRESULT f_rename (const TCHAR *path_old, const TCHAR *path_new)
 
FRESULT f_stat (const TCHAR *path, FILINFO *fno)
 
FRESULT f_chmod (const TCHAR *path, BYTE attr, BYTE mask)
 
FRESULT f_utime (const TCHAR *path, const FILINFO *fno)
 
FRESULT f_chdir (const TCHAR *path)
 
FRESULT f_chdrive (const TCHAR *path)
 
FRESULT f_getcwd (TCHAR *buff, UINT len)
 
FRESULT f_getfree (const TCHAR *path, DWORD *nclst, FATFS **fatfs)
 
FRESULT f_getlabel (const TCHAR *path, TCHAR *label, DWORD *vsn)
 
FRESULT f_setlabel (const TCHAR *label)
 
FRESULT f_forward (FIL *fp, UINT(*func)(const BYTE *, UINT), UINT btf, UINT *bf)
 
FRESULT f_expand (FIL *fp, FSIZE_t fsz, BYTE opt)
 
FRESULT f_mount (FATFS *fs, const TCHAR *path, BYTE opt)
 
FRESULT f_mkfs (const TCHAR *path, const MKFS_PARM *opt, void *work, UINT len)
 
FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void *work)
 
FRESULT f_setcp (WORD cp)
 
int f_putc (TCHAR c, FIL *fp)
 
int f_puts (const TCHAR *str, FIL *cp)
 
int f_printf (FIL *fp, const TCHAR *str,...)
 
TCHARf_gets (TCHAR *buff, int len, FIL *fp)
 
WCHAR ff_oem2uni (WCHAR oem, WORD cp)
 
WCHAR ff_uni2oem (DWORD uni, WORD cp)
 
DWORD ff_wtoupper (DWORD uni)
 
void * ff_memalloc (UINT msize)
 
void ff_memfree (void *mblock)
 

Macro Definition Documentation

◆ _T

#define _T (   x)    x

Definition at line 106 of file ff.h.

◆ _TEXT

#define _TEXT (   x)    x

Definition at line 107 of file ff.h.

◆ AM_ARC

#define AM_ARC   0x20 /* Archive */

Definition at line 415 of file ff.h.

◆ AM_DIR

#define AM_DIR   0x10 /* Directory */

Definition at line 414 of file ff.h.

◆ AM_HID

#define AM_HID   0x02 /* Hidden */

Definition at line 412 of file ff.h.

◆ AM_RDO

#define AM_RDO   0x01 /* Read only */

Definition at line 411 of file ff.h.

◆ AM_SYS

#define AM_SYS   0x04 /* System */

Definition at line 413 of file ff.h.

◆ CREATE_LINKMAP

#define CREATE_LINKMAP   ((FSIZE_t)0 - 1)

Definition at line 395 of file ff.h.

◆ f_eof

#define f_eof (   fp)    ((int)((fp)->fptr == (fp)->obj.objsize))

Definition at line 339 of file ff.h.

◆ f_error

#define f_error (   fp)    ((fp)->err)

Definition at line 340 of file ff.h.

◆ f_rewind

#define f_rewind (   fp)    f_lseek((fp), 0)

Definition at line 343 of file ff.h.

◆ f_rewinddir

#define f_rewinddir (   dp)    f_readdir((dp), 0)

Definition at line 344 of file ff.h.

◆ f_rmdir

#define f_rmdir (   path)    f_unlink(path)

Definition at line 345 of file ff.h.

◆ f_size

#define f_size (   fp)    ((fp)->obj.objsize)

Definition at line 342 of file ff.h.

◆ f_tell

#define f_tell (   fp)    ((fp)->fptr)

Definition at line 341 of file ff.h.

◆ f_unmount

#define f_unmount (   path)    f_mount(0, path, 0)

Definition at line 346 of file ff.h.

◆ FA_CREATE_ALWAYS

#define FA_CREATE_ALWAYS   0x08

Definition at line 390 of file ff.h.

◆ FA_CREATE_NEW

#define FA_CREATE_NEW   0x04

Definition at line 389 of file ff.h.

◆ FA_OPEN_ALWAYS

#define FA_OPEN_ALWAYS   0x10

Definition at line 391 of file ff.h.

◆ FA_OPEN_APPEND

#define FA_OPEN_APPEND   0x30

Definition at line 392 of file ff.h.

◆ FA_OPEN_EXISTING

#define FA_OPEN_EXISTING   0x00

Definition at line 388 of file ff.h.

◆ FA_READ

#define FA_READ   0x01

Definition at line 386 of file ff.h.

◆ FA_WRITE

#define FA_WRITE   0x02

Definition at line 387 of file ff.h.

◆ FF_DEFINED

#define FF_DEFINED   86631 /* Revision ID */

Definition at line 23 of file ff.h.

◆ FF_INTDEF

#define FF_INTDEF   1

Definition at line 57 of file ff.h.

◆ FM_ANY

#define FM_ANY   0x07

Definition at line 401 of file ff.h.

◆ FM_EXFAT

#define FM_EXFAT   0x04

Definition at line 400 of file ff.h.

◆ FM_FAT

#define FM_FAT   0x01

Definition at line 398 of file ff.h.

◆ FM_FAT32

#define FM_FAT32   0x02

Definition at line 399 of file ff.h.

◆ FM_SFD

#define FM_SFD   0x08

Definition at line 402 of file ff.h.

◆ FS_EXFAT

#define FS_EXFAT   4

Definition at line 408 of file ff.h.

◆ FS_FAT12

#define FS_FAT12   1

Definition at line 405 of file ff.h.

◆ FS_FAT16

#define FS_FAT16   2

Definition at line 406 of file ff.h.

◆ FS_FAT32

#define FS_FAT32   3

Definition at line 407 of file ff.h.

Typedef Documentation

◆ BYTE

typedef unsigned char BYTE

Definition at line 59 of file ff.h.

◆ DWORD

typedef unsigned long DWORD

Definition at line 61 of file ff.h.

◆ FSIZE_t

typedef DWORD FSIZE_t

Definition at line 82 of file ff.h.

◆ LBA_t

typedef DWORD LBA_t

Definition at line 83 of file ff.h.

◆ TCHAR

typedef char TCHAR

Definition at line 105 of file ff.h.

◆ UINT

typedef unsigned int UINT

Definition at line 58 of file ff.h.

◆ WCHAR

typedef WORD WCHAR

Definition at line 62 of file ff.h.

◆ WORD

typedef unsigned short WORD

Definition at line 60 of file ff.h.

Enumeration Type Documentation

◆ FRESULT

enum FRESULT
Enumerator
FR_OK 
FR_DISK_ERR 
FR_INT_ERR 
FR_NOT_READY 
FR_NO_FILE 
FR_NO_PATH 
FR_INVALID_NAME 
FR_DENIED 
FR_EXIST 
FR_INVALID_OBJECT 
FR_WRITE_PROTECTED 
FR_INVALID_DRIVE 
FR_NOT_ENABLED 
FR_NO_FILESYSTEM 
FR_MKFS_ABORTED 
FR_TIMEOUT 
FR_LOCKED 
FR_NOT_ENOUGH_CORE 
FR_TOO_MANY_OPEN_FILES 
FR_INVALID_PARAMETER 

Definition at line 276 of file ff.h.

276 {
277 FR_OK = 0, /* (0) Succeeded */
278 FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
279 FR_INT_ERR, /* (2) Assertion failed */
280 FR_NOT_READY, /* (3) The physical drive cannot work */
281 FR_NO_FILE, /* (4) Could not find the file */
282 FR_NO_PATH, /* (5) Could not find the path */
283 FR_INVALID_NAME, /* (6) The path name format is invalid */
284 FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
285 FR_EXIST, /* (8) Access denied due to prohibited access */
286 FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
287 FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
288 FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
289 FR_NOT_ENABLED, /* (12) The volume has no work area */
290 FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
291 FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
292 FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
293 FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
294 FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
295 FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
296 FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
297} FRESULT;
FRESULT
Definition ff.h:276
@ FR_NO_FILESYSTEM
Definition ff.h:290
@ FR_EXIST
Definition ff.h:285
@ FR_INVALID_PARAMETER
Definition ff.h:296
@ FR_INVALID_OBJECT
Definition ff.h:286
@ FR_TIMEOUT
Definition ff.h:292
@ FR_INVALID_DRIVE
Definition ff.h:288
@ FR_MKFS_ABORTED
Definition ff.h:291
@ FR_TOO_MANY_OPEN_FILES
Definition ff.h:295
@ FR_OK
Definition ff.h:277
@ FR_LOCKED
Definition ff.h:293
@ FR_INVALID_NAME
Definition ff.h:283
@ FR_DENIED
Definition ff.h:284
@ FR_NO_FILE
Definition ff.h:281
@ FR_DISK_ERR
Definition ff.h:278
@ FR_INT_ERR
Definition ff.h:279
@ FR_WRITE_PROTECTED
Definition ff.h:287
@ FR_NOT_READY
Definition ff.h:280
@ FR_NO_PATH
Definition ff.h:282
@ FR_NOT_ENOUGH_CORE
Definition ff.h:294
@ FR_NOT_ENABLED
Definition ff.h:289

Function Documentation

◆ f_chdir()

FRESULT f_chdir ( const TCHAR path)

Definition at line 4205 of file ff.c.

4208{
4209#if FF_STR_VOLUME_ID == 2
4210 UINT i;
4211#endif
4212 FRESULT res;
4213 DIR dj;
4214 FATFS *fs;
4216
4217
4218 /* Get logical drive */
4219 res = mount_volume(&path, &fs, 0);
4220 if (res == FR_OK) {
4221 dj.obj.fs = fs;
4222 INIT_NAMBUF(fs);
4223 res = follow_path(&dj, path); /* Follow the path */
4224 if (res == FR_OK) { /* Follow completed */
4225 if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it the start directory itself? */
4226 fs->cdir = dj.obj.sclust;
4227#if FF_FS_EXFAT
4228 if (fs->fs_type == FS_EXFAT) {
4229 fs->cdc_scl = dj.obj.c_scl;
4230 fs->cdc_size = dj.obj.c_size;
4231 fs->cdc_ofs = dj.obj.c_ofs;
4232 }
4233#endif
4234 } else {
4235 if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */
4236#if FF_FS_EXFAT
4237 if (fs->fs_type == FS_EXFAT) {
4238 fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */
4239 fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */
4240 fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
4241 fs->cdc_ofs = dj.blk_ofs;
4242 } else
4243#endif
4244 {
4245 fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */
4246 }
4247 } else {
4248 res = FR_NO_PATH; /* Reached but a file */
4249 }
4250 }
4251 }
4252 FREE_NAMBUF();
4253 if (res == FR_NO_FILE) res = FR_NO_PATH;
4254#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed if in Unix style volume ID */
4255 if (res == FR_OK) {
4256 for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */
4257 CurrVol = (BYTE)i;
4258 }
4259#endif
4260 }
4261
4262 LEAVE_FF(fs, res);
4263}
#define NS_NONAME
Definition ff.c:80
static FATFS * FatFs[FF_VOLUMES]
Definition ff.c:464
static FRESULT mount_volume(const TCHAR **path, FATFS **rfs, BYTE mode)
Definition ff.c:3332
#define LEAVE_FF(fs, res)
Definition ff.c:244
#define INIT_NAMBUF(fs)
Definition ff.c:545
#define FREE_NAMBUF()
Definition ff.c:546
static DWORD ld_dword(const BYTE *ptr)
Definition ff.c:623
static DWORD ld_clust(FATFS *fs, const BYTE *dir)
Definition ff.c:1817
#define NSFLAG
Definition ff.c:72
static BYTE CurrVol
Definition ff.c:468
#define DEF_NAMBUF
Definition ff.c:544
#define XDIR_FstClus
Definition ff.c:185
static FRESULT follow_path(DIR *dp, const TCHAR *path)
Definition ff.c:3003
unsigned int UINT
Definition ff.h:58
#define AM_DIR
Definition ff.h:414
unsigned char BYTE
Definition ff.h:59
#define FS_EXFAT
Definition ff.h:408
unsigned long DWORD
Definition ff.h:61
#define FF_VOLUMES
Definition ffconf.h:172
Definition ff.h:228
BYTE * dir
Definition ff.h:233
FFOBJID obj
Definition ff.h:229
BYTE fn[12]
Definition ff.h:234
DWORD blk_ofs
Definition ff.h:236
Definition ff.h:132
DWORD cdir
Definition ff.h:158
BYTE fs_type
Definition ff.h:133
FSIZE_t objsize
Definition ff.h:188
FATFS * fs
Definition ff.h:183
BYTE stat
Definition ff.h:186
DWORD sclust
Definition ff.h:187
BYTE attr
Definition ff.h:185

◆ f_chdrive()

FRESULT f_chdrive ( const TCHAR path)

Definition at line 4188 of file ff.c.

4191{
4192 int vol;
4193
4194
4195 /* Get logical drive number */
4196 vol = get_ldnumber(&path);
4197 if (vol < 0) return FR_INVALID_DRIVE;
4198 CurrVol = (BYTE)vol; /* Set it as current volume */
4199
4200 return FR_OK;
4201}
static int get_ldnumber(const TCHAR **path)
Definition ff.c:3090

◆ f_chmod()

FRESULT f_chmod ( const TCHAR path,
BYTE  attr,
BYTE  mask 
)

◆ f_close()

FRESULT f_close ( FIL fp)

Definition at line 4152 of file ff.c.

4155{
4156 FRESULT res;
4157 FATFS *fs;
4158
4159#if !FF_FS_READONLY
4160 res = f_sync(fp); /* Flush cached data */
4161 if (res == FR_OK)
4162#endif
4163 {
4164 res = validate(&fp->obj, &fs); /* Lock volume */
4165 if (res == FR_OK) {
4166#if FF_FS_LOCK != 0
4167 res = dec_lock(fp->obj.lockid); /* Decrement file open counter */
4168 if (res == FR_OK) fp->obj.fs = 0; /* Invalidate file object */
4169#else
4170 fp->obj.fs = 0; /* Invalidate file object */
4171#endif
4172#if FF_FS_REENTRANT
4173 unlock_fs(fs, FR_OK); /* Unlock volume */
4174#endif
4175 }
4176 }
4177 return res;
4178}
FILE * fp
Definition FileIo.c:56
FRESULT f_sync(FIL *fp)
Definition ff.c:4071
static FRESULT validate(FFOBJID *obj, FATFS **rfs)
Definition ff.c:3561
static FRESULT dec_lock(UINT i)
Definition ff.c:984

◆ f_closedir()

FRESULT f_closedir ( DIR dp)

Definition at line 4597 of file ff.c.

4600{
4601 FRESULT res;
4602 FATFS *fs;
4603
4604
4605 res = validate(&dp->obj, &fs); /* Check validity of the file object */
4606 if (res == FR_OK) {
4607#if FF_FS_LOCK != 0
4608 if (dp->obj.lockid) res = dec_lock(dp->obj.lockid); /* Decrement sub-directory open counter */
4609 if (res == FR_OK) dp->obj.fs = 0; /* Invalidate directory object */
4610#else
4611 dp->obj.fs = 0; /* Invalidate directory object */
4612#endif
4613#if FF_FS_REENTRANT
4614 unlock_fs(fs, FR_OK); /* Unlock volume */
4615#endif
4616 }
4617 return res;
4618}
UINT lockid
Definition ff.h:197

◆ f_expand()

FRESULT f_expand ( FIL fp,
FSIZE_t  fsz,
BYTE  opt 
)

◆ f_fdisk()

FRESULT f_fdisk ( BYTE  pdrv,
const LBA_t  ptbl[],
void *  work 
)

◆ f_findfirst()

FRESULT f_findfirst ( DIR dp,
FILINFO fno,
const TCHAR path,
const TCHAR pattern 
)

◆ f_findnext()

FRESULT f_findnext ( DIR dp,
FILINFO fno 
)

◆ f_forward()

FRESULT f_forward ( FIL fp,
UINT(*)(const BYTE *, UINT func,
UINT  btf,
UINT bf 
)

◆ f_getcwd()

FRESULT f_getcwd ( TCHAR buff,
UINT  len 
)

◆ f_getfree()

FRESULT f_getfree ( const TCHAR path,
DWORD nclst,
FATFS **  fatfs 
)

Definition at line 4750 of file ff.c.

4755{
4756 FRESULT res;
4757 FATFS *fs;
4758 DWORD nfree, clst, stat;
4759 LBA_t sect;
4760 UINT i;
4761 FFOBJID obj;
4762
4763
4764 /* Get logical drive */
4765 res = mount_volume(&path, &fs, 0);
4766 if (res == FR_OK) {
4767 *fatfs = fs; /* Return ptr to the fs object */
4768 /* If free_clst is valid, return it without full FAT scan */
4769 if (fs->free_clst <= fs->n_fatent - 2) {
4770 *nclst = fs->free_clst;
4771 } else {
4772 /* Scan FAT to obtain number of free clusters */
4773 nfree = 0;
4774 if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */
4775 clst = 2; obj.fs = fs;
4776 do {
4777 stat = get_fat(&obj, clst);
4778 if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
4779 if (stat == 1) { res = FR_INT_ERR; break; }
4780 if (stat == 0) nfree++;
4781 } while (++clst < fs->n_fatent);
4782 } else {
4783#if FF_FS_EXFAT
4784 if (fs->fs_type == FS_EXFAT) { /* exFAT: Scan allocation bitmap */
4785 BYTE bm;
4786 UINT b;
4787
4788 clst = fs->n_fatent - 2; /* Number of clusters */
4789 sect = fs->bitbase; /* Bitmap sector */
4790 i = 0; /* Offset in the sector */
4791 do { /* Counts numbuer of bits with zero in the bitmap */
4792 if (i == 0) {
4793 res = move_window(fs, sect++);
4794 if (res != FR_OK) break;
4795 }
4796 for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) {
4797 if (!(bm & 1)) nfree++;
4798 bm >>= 1;
4799 }
4800 i = (i + 1) % SS(fs);
4801 } while (clst);
4802 } else
4803#endif
4804 { /* FAT16/32: Scan WORD/DWORD FAT entries */
4805 clst = fs->n_fatent; /* Number of entries */
4806 sect = fs->fatbase; /* Top of the FAT */
4807 i = 0; /* Offset in the sector */
4808 do { /* Counts numbuer of entries with zero in the FAT */
4809 if (i == 0) {
4810 res = move_window(fs, sect++);
4811 if (res != FR_OK) break;
4812 }
4813 if (fs->fs_type == FS_FAT16) {
4814 if (ld_word(fs->win + i) == 0) nfree++;
4815 i += 2;
4816 } else {
4817 if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++;
4818 i += 4;
4819 }
4820 i %= SS(fs);
4821 } while (--clst);
4822 }
4823 }
4824 if (res == FR_OK) { /* Update parameters if succeeded */
4825 *nclst = nfree; /* Return the free clusters */
4826 fs->free_clst = nfree; /* Now free_clst is valid */
4827 fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */
4828 }
4829 }
4830 }
4831
4832 LEAVE_FF(fs, res);
4833}
static uint32_t b
Definition Common.c:37
static FRESULT move_window(FATFS *fs, LBA_t sect)
Definition ff.c:1047
#define SS(fs)
Definition ff.c:263
static DWORD get_fat(FFOBJID *obj, DWORD clst)
Definition ff.c:1131
static WORD ld_word(const BYTE *ptr)
Definition ff.c:614
DWORD LBA_t
Definition ff.h:83
#define FS_FAT16
Definition ff.h:406
#define FS_FAT12
Definition ff.h:405
BYTE win[FF_MAX_SS]
Definition ff.h:175
LBA_t fatbase
Definition ff.h:168
BYTE fsi_flag
Definition ff.h:137
DWORD n_fatent
Definition ff.h:165
DWORD free_clst
Definition ff.h:155
Definition ff.h:182

◆ f_getlabel()

FRESULT f_getlabel ( const TCHAR path,
TCHAR label,
DWORD vsn 
)

◆ f_gets()

TCHAR * f_gets ( TCHAR buff,
int  len,
FIL fp 
)

Definition at line 6338 of file ff.c.

6343{
6344 int nc = 0;
6345 TCHAR *p = buff;
6346 BYTE s[4];
6347 UINT rc;
6348 DWORD dc;
6349#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2
6350 WCHAR wc;
6351#endif
6352#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3
6353 UINT ct;
6354#endif
6355
6356#if FF_USE_LFN && FF_LFN_UNICODE /* With code conversion (Unicode API) */
6357 /* Make a room for the character and terminator */
6358 if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2;
6359 if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4;
6360 if (FF_LFN_UNICODE == 3) len -= 1;
6361 while (nc < len) {
6362#if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */
6363 f_read(fp, s, 1, &rc); /* Get a code unit */
6364 if (rc != 1) break; /* EOF? */
6365 wc = s[0];
6366 if (dbc_1st((BYTE)wc)) { /* DBC 1st byte? */
6367 f_read(fp, s, 1, &rc); /* Get 2nd byte */
6368 if (rc != 1 || !dbc_2nd(s[0])) continue; /* Wrong code? */
6369 wc = wc << 8 | s[0];
6370 }
6371 dc = ff_oem2uni(wc, CODEPAGE); /* Convert ANSI/OEM into Unicode */
6372 if (dc == 0) continue; /* Conversion error? */
6373#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */
6374 f_read(fp, s, 2, &rc); /* Get a code unit */
6375 if (rc != 2) break; /* EOF? */
6376 dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1];
6377 if (IsSurrogateL(dc)) continue; /* Broken surrogate pair? */
6378 if (IsSurrogateH(dc)) { /* High surrogate? */
6379 f_read(fp, s, 2, &rc); /* Get low surrogate */
6380 if (rc != 2) break; /* EOF? */
6381 wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1];
6382 if (!IsSurrogateL(wc)) continue; /* Broken surrogate pair? */
6383 dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF); /* Merge surrogate pair */
6384 }
6385#else /* Read a character in UTF-8 */
6386 f_read(fp, s, 1, &rc); /* Get a code unit */
6387 if (rc != 1) break; /* EOF? */
6388 dc = s[0];
6389 if (dc >= 0x80) { /* Multi-byte sequence? */
6390 ct = 0;
6391 if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } /* 2-byte sequence? */
6392 if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte sequence? */
6393 if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte sequence? */
6394 if (ct == 0) continue;
6395 f_read(fp, s, ct, &rc); /* Get trailing bytes */
6396 if (rc != ct) break;
6397 rc = 0;
6398 do { /* Merge the byte sequence */
6399 if ((s[rc] & 0xC0) != 0x80) break;
6400 dc = dc << 6 | (s[rc] & 0x3F);
6401 } while (++rc < ct);
6402 if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue; /* Wrong encoding? */
6403 }
6404#endif
6405 /* A code point is avaialble in dc to be output */
6406
6407 if (FF_USE_STRFUNC == 2 && dc == '\r') continue; /* Strip \r off if needed */
6408#if FF_LFN_UNICODE == 1 || FF_LFN_UNICODE == 3 /* Output it in UTF-16/32 encoding */
6409 if (FF_LFN_UNICODE == 1 && dc >= 0x10000) { /* Out of BMP at UTF-16? */
6410 *p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++; /* Make and output high surrogate */
6411 dc = 0xDC00 | (dc & 0x3FF); /* Make low surrogate */
6412 }
6413 *p++ = (TCHAR)dc; nc++;
6414 if (dc == '\n') break; /* End of line? */
6415#elif FF_LFN_UNICODE == 2 /* Output it in UTF-8 encoding */
6416 if (dc < 0x80) { /* Single byte? */
6417 *p++ = (TCHAR)dc;
6418 nc++;
6419 if (dc == '\n') break; /* End of line? */
6420 } else {
6421 if (dc < 0x800) { /* 2-byte sequence? */
6422 *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F));
6423 *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
6424 nc += 2;
6425 } else {
6426 if (dc < 0x10000) { /* 3-byte sequence? */
6427 *p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F));
6428 *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F));
6429 *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
6430 nc += 3;
6431 } else { /* 4-byte sequence? */
6432 *p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07));
6433 *p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F));
6434 *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F));
6435 *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F));
6436 nc += 4;
6437 }
6438 }
6439 }
6440#endif
6441 }
6442
6443#else /* Byte-by-byte read without any conversion (ANSI/OEM API) */
6444 len -= 1; /* Make a room for the terminator */
6445 while (nc < len) {
6446 f_read(fp, s, 1, &rc); /* Get a byte */
6447 if (rc != 1) break; /* EOF? */
6448 dc = s[0];
6449 if (FF_USE_STRFUNC == 2 && dc == '\r') continue;
6450 *p++ = (TCHAR)dc; nc++;
6451 if (dc == '\n') break;
6452 }
6453#endif
6454
6455 *p = 0; /* Terminate the string */
6456 return nc ? buff : 0; /* When no data read due to EOF or error, return with error. */
6457}
#define CODEPAGE
Definition ff.c:591
#define IsSurrogate(c)
Definition ff.c:53
static int dbc_1st(BYTE c)
Definition ff.c:688
#define IsSurrogateL(c)
Definition ff.c:55
FRESULT f_read(FIL *fp, void *buff, UINT btr, UINT *br)
Definition ff.c:3850
#define IsSurrogateH(c)
Definition ff.c:54
static int dbc_2nd(BYTE c)
Definition ff.c:708
char TCHAR
Definition ff.h:105
WORD WCHAR
Definition ff.h:62
WCHAR ff_oem2uni(WCHAR oem, WORD cp)
#define FF_STRF_ENCODE
Definition ffconf.h:65
#define FF_LFN_UNICODE
Definition ffconf.h:139
#define FF_USE_STRFUNC
Definition ffconf.h:62

◆ f_lseek()

FRESULT f_lseek ( FIL fp,
FSIZE_t  ofs 
)

Definition at line 4367 of file ff.c.

4371{
4372 FRESULT res;
4373 FATFS *fs;
4374 DWORD clst, bcs;
4375 LBA_t nsect;
4376 FSIZE_t ifptr;
4377#if FF_USE_FASTSEEK
4378 DWORD cl, pcl, ncl, tcl, tlen, ulen;
4379 DWORD *tbl;
4380 LBA_t dsc;
4381#endif
4382
4383 res = validate(&fp->obj, &fs); /* Check validity of the file object */
4384 if (res == FR_OK) res = (FRESULT)fp->err;
4385#if FF_FS_EXFAT && !FF_FS_READONLY
4386 if (res == FR_OK && fs->fs_type == FS_EXFAT) {
4387 res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */
4388 }
4389#endif
4390 if (res != FR_OK) LEAVE_FF(fs, res);
4391
4392#if FF_USE_FASTSEEK
4393 if (fp->cltbl) { /* Fast seek */
4394 if (ofs == CREATE_LINKMAP) { /* Create CLMT */
4395 tbl = fp->cltbl;
4396 tlen = *tbl++; ulen = 2; /* Given table size and required table size */
4397 cl = fp->obj.sclust; /* Origin of the chain */
4398 if (cl != 0) {
4399 do {
4400 /* Get a fragment */
4401 tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */
4402 do {
4403 pcl = cl; ncl++;
4404 cl = get_fat(&fp->obj, cl);
4405 if (cl <= 1) ABORT(fs, FR_INT_ERR);
4406 if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
4407 } while (cl == pcl + 1);
4408 if (ulen <= tlen) { /* Store the length and top of the fragment */
4409 *tbl++ = ncl; *tbl++ = tcl;
4410 }
4411 } while (cl < fs->n_fatent); /* Repeat until end of chain */
4412 }
4413 *fp->cltbl = ulen; /* Number of items used */
4414 if (ulen <= tlen) {
4415 *tbl = 0; /* Terminate table */
4416 } else {
4417 res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */
4418 }
4419 } else { /* Fast seek */
4420 if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */
4421 fp->fptr = ofs; /* Set file pointer */
4422 if (ofs > 0) {
4423 fp->clust = clmt_clust(fp, ofs - 1);
4424 dsc = clst2sect(fs, fp->clust);
4425 if (dsc == 0) ABORT(fs, FR_INT_ERR);
4426 dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1);
4427 if (fp->fptr % SS(fs) && dsc != fp->sect) { /* Refill sector cache if needed */
4428#if !FF_FS_TINY
4429#if !FF_FS_READONLY
4430 if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
4431 if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
4432 fp->flag &= (BYTE)~FA_DIRTY;
4433 }
4434#endif
4435 if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */
4436#endif
4437 fp->sect = dsc;
4438 }
4439 }
4440 }
4441 } else
4442#endif
4443
4444 /* Normal Seek */
4445 {
4446#if FF_FS_EXFAT
4447 if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4 GiB - 1 if at FATxx */
4448#endif
4449 if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) { /* In read-only mode, clip offset with the file size */
4450 ofs = fp->obj.objsize;
4451 }
4452 ifptr = fp->fptr;
4453 fp->fptr = nsect = 0;
4454 if (ofs > 0) {
4455 bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */
4456 if (ifptr > 0 &&
4457 (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
4458 fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */
4459 ofs -= fp->fptr;
4460 clst = fp->clust;
4461 } else { /* When seek to back cluster, */
4462 clst = fp->obj.sclust; /* start from the first cluster */
4463#if !FF_FS_READONLY
4464 if (clst == 0) { /* If no cluster chain, create a new chain */
4465 clst = create_chain(&fp->obj, 0);
4466 if (clst == 1) ABORT(fs, FR_INT_ERR);
4467 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
4468 fp->obj.sclust = clst;
4469 }
4470#endif
4471 fp->clust = clst;
4472 }
4473 if (clst != 0) {
4474 while (ofs > bcs) { /* Cluster following loop */
4475 ofs -= bcs; fp->fptr += bcs;
4476#if !FF_FS_READONLY
4477 if (fp->flag & FA_WRITE) { /* Check if in write mode or not */
4478 if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) { /* No FAT chain object needs correct objsize to generate FAT value */
4479 fp->obj.objsize = fp->fptr;
4480 fp->flag |= FA_MODIFIED;
4481 }
4482 clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */
4483 if (clst == 0) { /* Clip file size in case of disk full */
4484 ofs = 0; break;
4485 }
4486 } else
4487#endif
4488 {
4489 clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */
4490 }
4491 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
4492 if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR);
4493 fp->clust = clst;
4494 }
4495 fp->fptr += ofs;
4496 if (ofs % SS(fs)) {
4497 nsect = clst2sect(fs, clst); /* Current sector */
4498 if (nsect == 0) ABORT(fs, FR_INT_ERR);
4499 nsect += (DWORD)(ofs / SS(fs));
4500 }
4501 }
4502 }
4503 if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */
4504 fp->obj.objsize = fp->fptr;
4505 fp->flag |= FA_MODIFIED;
4506 }
4507 if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */
4508#if !FF_FS_TINY
4509#if !FF_FS_READONLY
4510 if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
4511 if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
4512 fp->flag &= (BYTE)~FA_DIRTY;
4513 }
4514#endif
4515 if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
4516#endif
4517 fp->sect = nsect;
4518 }
4519 }
4520
4521 LEAVE_FF(fs, res);
4522}
DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
@ RES_OK
Definition diskio.h:17
DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
static DWORD create_chain(FFOBJID *obj, DWORD clst)
Definition ff.c:1494
#define ABORT(fs, res)
Definition ff.c:234
static LBA_t clst2sect(FATFS *fs, DWORD clst)
Definition ff.c:1114
#define FA_MODIFIED
Definition ff.c:60
#define FA_DIRTY
Definition ff.c:61
DWORD FSIZE_t
Definition ff.h:82
#define CREATE_LINKMAP
Definition ff.h:395
#define FA_WRITE
Definition ff.h:387
#define FF_FS_EXFAT
Definition ffconf.h:237
#define FF_FS_READONLY
Definition ffconf.h:14
BYTE pdrv
Definition ff.h:134
WORD csize
Definition ff.h:140

◆ f_mkdir()

FRESULT f_mkdir ( const TCHAR path)

Definition at line 4986 of file ff.c.

4989{
4990 FRESULT res;
4991 DIR dj;
4992 FFOBJID sobj;
4993 FATFS *fs;
4994 DWORD dcl, pcl, tm;
4996
4997
4998 res = mount_volume(&path, &fs, FA_WRITE); /* Get logical drive */
4999 if (res == FR_OK) {
5000 dj.obj.fs = fs;
5001 INIT_NAMBUF(fs);
5002 res = follow_path(&dj, path); /* Follow the file path */
5003 if (res == FR_OK) res = FR_EXIST; /* Name collision? */
5004 if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */
5005 res = FR_INVALID_NAME;
5006 }
5007 if (res == FR_NO_FILE) { /* It is clear to create a new directory */
5008 sobj.fs = fs; /* New object id to create a new chain */
5009 dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */
5010 res = FR_OK;
5011 if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */
5012 if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */
5013 if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */
5014 tm = GET_FATTIME();
5015 if (res == FR_OK) {
5016 res = dir_clear(fs, dcl); /* Clean up the new table */
5017 if (res == FR_OK) {
5018 if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */
5019 memset(fs->win + DIR_Name, ' ', 11); /* Create "." entry */
5020 fs->win[DIR_Name] = '.';
5021 fs->win[DIR_Attr] = AM_DIR;
5022 st_dword(fs->win + DIR_ModTime, tm);
5023 st_clust(fs, fs->win, dcl);
5024 memcpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */
5025 fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
5026 st_clust(fs, fs->win + SZDIRE, pcl);
5027 fs->wflag = 1;
5028 }
5029 res = dir_register(&dj); /* Register the object to the parent directoy */
5030 }
5031 }
5032 if (res == FR_OK) {
5033#if FF_FS_EXFAT
5034 if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */
5035 st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */
5036 st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */
5037 st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* Directory size needs to be valid */
5038 st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs));
5039 fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */
5040 fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */
5041 res = store_xdir(&dj);
5042 } else
5043#endif
5044 {
5045 st_dword(dj.dir + DIR_ModTime, tm); /* Created time */
5046 st_clust(fs, dj.dir, dcl); /* Table start cluster */
5047 dj.dir[DIR_Attr] = AM_DIR; /* Attribute */
5048 fs->wflag = 1;
5049 }
5050 if (res == FR_OK) {
5051 res = sync_fs(fs);
5052 }
5053 } else {
5054 remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */
5055 }
5056 }
5057 FREE_NAMBUF();
5058 }
5059
5060 LEAVE_FF(fs, res);
5061}
#define NS_DOT
Definition ff.c:78
static void st_clust(FATFS *fs, BYTE *dir, DWORD cl)
Definition ff.c:1834
#define XDIR_ValidFileSize
Definition ff.c:184
#define GET_FATTIME()
Definition ff.c:274
#define XDIR_FileSize
Definition ff.c:186
#define SZDIRE
Definition ff.c:188
#define DIR_ModTime
Definition ff.c:158
#define XDIR_Attr
Definition ff.c:172
static FRESULT dir_register(DIR *dp)
Definition ff.c:2434
#define XDIR_GenFlags
Definition ff.c:181
#define DIR_Attr
Definition ff.c:152
static FRESULT dir_clear(FATFS *fs, DWORD clst)
Definition ff.c:1627
static FRESULT sync_fs(FATFS *fs)
Definition ff.c:1078
#define XDIR_ModTime
Definition ff.c:174
static void st_dword(BYTE *ptr, DWORD val)
Definition ff.c:658
static FRESULT remove_chain(FFOBJID *obj, DWORD clst, DWORD pclst)
Definition ff.c:1399
#define DIR_Name
Definition ff.c:151
#define FF_FS_RPATH
Definition ffconf.h:159
BYTE wflag
Definition ff.h:136

◆ f_mkfs()

FRESULT f_mkfs ( const TCHAR path,
const MKFS_PARM opt,
void *  work,
UINT  len 
)

◆ f_mount()

FRESULT f_mount ( FATFS fs,
const TCHAR path,
BYTE  opt 
)

Definition at line 3605 of file ff.c.

3610{
3611 FATFS *cfs;
3612 int vol;
3613 FRESULT res;
3614 const TCHAR *rp = path;
3615
3616
3617 /* Get logical drive number */
3618 vol = get_ldnumber(&rp);
3619 if (vol < 0) return FR_INVALID_DRIVE;
3620 cfs = FatFs[vol]; /* Pointer to fs object */
3621
3622 if (cfs) {
3623#if FF_FS_LOCK != 0
3624 clear_lock(cfs);
3625#endif
3626#if FF_FS_REENTRANT /* Discard sync object of the current volume */
3627 if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR;
3628#endif
3629 cfs->fs_type = 0; /* Clear old fs object */
3630 }
3631
3632 if (fs) {
3633 fs->fs_type = 0; /* Clear new fs object */
3634#if FF_FS_REENTRANT /* Create sync object for the new volume */
3635 if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR;
3636#endif
3637 }
3638 FatFs[vol] = fs; /* Register new fs object */
3639
3640 if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted later */
3641
3642 res = mount_volume(&path, &fs, 0); /* Force mounted the volume */
3643 LEAVE_FF(fs, res);
3644}
static void clear_lock(FATFS *fs)
Definition ff.c:1006

◆ f_open()

FRESULT f_open ( FIL fp,
const TCHAR path,
BYTE  mode 
)

Definition at line 3653 of file ff.c.

3658{
3659 FRESULT res;
3660 DIR dj;
3661 FATFS *fs;
3662#if !FF_FS_READONLY
3663 DWORD cl, bcs, clst, tm;
3664 LBA_t sc;
3665 FSIZE_t ofs;
3666#endif
3668
3669
3670 if (!fp) return FR_INVALID_OBJECT;
3671
3672 /* Get logical drive number */
3674 res = mount_volume(&path, &fs, mode);
3675 if (res == FR_OK) {
3676 dj.obj.fs = fs;
3677 INIT_NAMBUF(fs);
3678 res = follow_path(&dj, path); /* Follow the file path */
3679#if !FF_FS_READONLY /* Read/Write configuration */
3680 if (res == FR_OK) {
3681 if (dj.fn[NSFLAG] & NS_NONAME) { /* Origin directory itself? */
3682 res = FR_INVALID_NAME;
3683 }
3684#if FF_FS_LOCK != 0
3685 else {
3686 res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */
3687 }
3688#endif
3689 }
3690 /* Create or Open a file */
3692 if (res != FR_OK) { /* No file, create new */
3693 if (res == FR_NO_FILE) { /* There is no file to open, create a new entry */
3694#if FF_FS_LOCK != 0
3696#else
3697 res = dir_register(&dj);
3698#endif
3699 }
3700 mode |= FA_CREATE_ALWAYS; /* File is created */
3701 }
3702 else { /* Any object with the same name is already existing */
3703 if (dj.obj.attr & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
3704 res = FR_DENIED;
3705 } else {
3706 if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */
3707 }
3708 }
3709 if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate the file if overwrite mode */
3710#if FF_FS_EXFAT
3711 if (fs->fs_type == FS_EXFAT) {
3712 /* Get current allocation info */
3713 fp->obj.fs = fs;
3714 init_alloc_info(fs, &fp->obj);
3715 /* Set directory entry block initial state */
3716 memset(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */
3717 memset(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */
3718 fs->dirbuf[XDIR_Attr] = AM_ARC;
3719 st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME());
3720 fs->dirbuf[XDIR_GenFlags] = 1;
3721 res = store_xdir(&dj);
3722 if (res == FR_OK && fp->obj.sclust != 0) { /* Remove the cluster chain if exist */
3723 res = remove_chain(&fp->obj, fp->obj.sclust, 0);
3724 fs->last_clst = fp->obj.sclust - 1; /* Reuse the cluster hole */
3725 }
3726 } else
3727#endif
3728 {
3729 /* Set directory entry initial state */
3730 tm = GET_FATTIME(); /* Set created time */
3731 st_dword(dj.dir + DIR_CrtTime, tm);
3732 st_dword(dj.dir + DIR_ModTime, tm);
3733 cl = ld_clust(fs, dj.dir); /* Get current cluster chain */
3734 dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */
3735 st_clust(fs, dj.dir, 0); /* Reset file allocation info */
3736 st_dword(dj.dir + DIR_FileSize, 0);
3737 fs->wflag = 1;
3738 if (cl != 0) { /* Remove the cluster chain if exist */
3739 sc = fs->winsect;
3740 res = remove_chain(&dj.obj, cl, 0);
3741 if (res == FR_OK) {
3742 res = move_window(fs, sc);
3743 fs->last_clst = cl - 1; /* Reuse the cluster hole */
3744 }
3745 }
3746 }
3747 }
3748 }
3749 else { /* Open an existing file */
3750 if (res == FR_OK) { /* Is the object exsiting? */
3751 if (dj.obj.attr & AM_DIR) { /* File open against a directory */
3752 res = FR_NO_FILE;
3753 } else {
3754 if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */
3755 res = FR_DENIED;
3756 }
3757 }
3758 }
3759 }
3760 if (res == FR_OK) {
3761 if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED; /* Set file change flag if created or overwritten */
3762 fp->dir_sect = fs->winsect; /* Pointer to the directory entry */
3763 fp->dir_ptr = dj.dir;
3764#if FF_FS_LOCK != 0
3765 fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */
3766 if (fp->obj.lockid == 0) res = FR_INT_ERR;
3767#endif
3768 }
3769#else /* R/O configuration */
3770 if (res == FR_OK) {
3771 if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it origin directory itself? */
3772 res = FR_INVALID_NAME;
3773 } else {
3774 if (dj.obj.attr & AM_DIR) { /* Is it a directory? */
3775 res = FR_NO_FILE;
3776 }
3777 }
3778 }
3779#endif
3780
3781 if (res == FR_OK) {
3782#if FF_FS_EXFAT
3783 if (fs->fs_type == FS_EXFAT) {
3784 fp->obj.c_scl = dj.obj.sclust; /* Get containing directory info */
3785 fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
3786 fp->obj.c_ofs = dj.blk_ofs;
3787 init_alloc_info(fs, &fp->obj);
3788 } else
3789#endif
3790 {
3791 fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */
3792 fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize);
3793 }
3794#if FF_USE_FASTSEEK
3795 fp->cltbl = 0; /* Disable fast seek mode */
3796#endif
3797 fp->obj.fs = fs; /* Validate the file object */
3798 fp->obj.id = fs->id;
3799 fp->flag = mode; /* Set file access mode */
3800 fp->err = 0; /* Clear error flag */
3801 fp->sect = 0; /* Invalidate current data sector */
3802 fp->fptr = 0; /* Set file pointer top of the file */
3803#if !FF_FS_READONLY
3804#if !FF_FS_TINY
3805 memset(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */
3806#endif
3807 if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
3808 fp->fptr = fp->obj.objsize; /* Offset to seek */
3809 bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */
3810 clst = fp->obj.sclust; /* Follow the cluster chain */
3811 for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) {
3812 clst = get_fat(&fp->obj, clst);
3813 if (clst <= 1) res = FR_INT_ERR;
3814 if (clst == 0xFFFFFFFF) res = FR_DISK_ERR;
3815 }
3816 fp->clust = clst;
3817 if (res == FR_OK && ofs % SS(fs)) { /* Fill sector buffer if not on the sector boundary */
3818 sc = clst2sect(fs, clst);
3819 if (sc == 0) {
3820 res = FR_INT_ERR;
3821 } else {
3822 fp->sect = sc + (DWORD)(ofs / SS(fs));
3823#if !FF_FS_TINY
3824 if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR;
3825#endif
3826 }
3827 }
3828#if FF_FS_LOCK != 0
3829 if (res != FR_OK) dec_lock(fp->obj.lockid); /* Decrement file open counter if seek failed */
3830#endif
3831 }
3832#endif
3833 }
3834
3835 FREE_NAMBUF();
3836 }
3837
3838 if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */
3839
3840 LEAVE_FF(fs, res);
3841}
static UINT inc_lock(DIR *dp, int acc)
Definition ff.c:953
#define DIR_CrtTime
Definition ff.c:155
#define XDIR_CrtTime
Definition ff.c:173
static int enq_lock(void)
Definition ff.c:944
#define DIR_FileSize
Definition ff.c:160
#define FA_SEEKEND
Definition ff.c:59
static FRESULT chk_lock(DIR *dp, int acc)
Definition ff.c:917
#define FA_OPEN_ALWAYS
Definition ff.h:391
#define FA_READ
Definition ff.h:386
#define FA_CREATE_NEW
Definition ff.h:389
#define FA_OPEN_APPEND
Definition ff.h:392
#define AM_RDO
Definition ff.h:411
#define AM_ARC
Definition ff.h:415
#define FA_CREATE_ALWAYS
Definition ff.h:390
WORD id
Definition ff.h:138
LBA_t winsect
Definition ff.h:174
DWORD last_clst
Definition ff.h:154

◆ f_opendir()

FRESULT f_opendir ( DIR dp,
const TCHAR path 
)

Definition at line 4531 of file ff.c.

4535{
4536 FRESULT res;
4537 FATFS *fs;
4539
4540
4541 if (!dp) return FR_INVALID_OBJECT;
4542
4543 /* Get logical drive */
4544 res = mount_volume(&path, &fs, 0);
4545 if (res == FR_OK) {
4546 dp->obj.fs = fs;
4547 INIT_NAMBUF(fs);
4548 res = follow_path(dp, path); /* Follow the path to the directory */
4549 if (res == FR_OK) { /* Follow completed */
4550 if (!(dp->fn[NSFLAG] & NS_NONAME)) { /* It is not the origin directory itself */
4551 if (dp->obj.attr & AM_DIR) { /* This object is a sub-directory */
4552#if FF_FS_EXFAT
4553 if (fs->fs_type == FS_EXFAT) {
4554 dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */
4555 dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat;
4556 dp->obj.c_ofs = dp->blk_ofs;
4557 init_alloc_info(fs, &dp->obj); /* Get object allocation info */
4558 } else
4559#endif
4560 {
4561 dp->obj.sclust = ld_clust(fs, dp->dir); /* Get object allocation info */
4562 }
4563 } else { /* This object is a file */
4564 res = FR_NO_PATH;
4565 }
4566 }
4567 if (res == FR_OK) {
4568 dp->obj.id = fs->id;
4569 res = dir_sdi(dp, 0); /* Rewind directory */
4570#if FF_FS_LOCK != 0
4571 if (res == FR_OK) {
4572 if (dp->obj.sclust != 0) {
4573 dp->obj.lockid = inc_lock(dp, 0); /* Lock the sub directory */
4574 if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES;
4575 } else {
4576 dp->obj.lockid = 0; /* Root directory need not to be locked */
4577 }
4578 }
4579#endif
4580 }
4581 }
4582 FREE_NAMBUF();
4583 if (res == FR_NO_FILE) res = FR_NO_PATH;
4584 }
4585 if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function faild */
4586
4587 LEAVE_FF(fs, res);
4588}
static FRESULT dir_sdi(DIR *dp, DWORD ofs)
Definition ff.c:1666
WORD id
Definition ff.h:184

◆ f_printf()

int f_printf ( FIL fp,
const TCHAR str,
  ... 
)

Definition at line 6801 of file ff.c.

6806{
6807 va_list arp;
6808 putbuff pb;
6809 UINT i, j, w, f, r;
6810 int prec;
6811#if FF_PRINT_LLI && FF_INTDEF == 2
6812 QWORD v;
6813#else
6814 DWORD v;
6815#endif
6816 TCHAR tc, pad, *tp;
6817 TCHAR nul = 0;
6818 char d, str[SZ_NUM_BUF];
6819
6820
6821 putc_init(&pb, fp);
6822
6823 va_start(arp, fmt);
6824
6825 for (;;) {
6826 tc = *fmt++;
6827 if (tc == 0) break; /* End of format string */
6828 if (tc != '%') { /* Not an escape character (pass-through) */
6829 putc_bfd(&pb, tc);
6830 continue;
6831 }
6832 f = w = 0; pad = ' '; prec = -1; /* Initialize parms */
6833 tc = *fmt++;
6834 if (tc == '0') { /* Flag: '0' padded */
6835 pad = '0'; tc = *fmt++;
6836 } else if (tc == '-') { /* Flag: Left aligned */
6837 f = 2; tc = *fmt++;
6838 }
6839 if (tc == '*') { /* Minimum width from an argument */
6840 w = va_arg(arp, int);
6841 tc = *fmt++;
6842 } else {
6843 while (IsDigit(tc)) { /* Minimum width */
6844 w = w * 10 + tc - '0';
6845 tc = *fmt++;
6846 }
6847 }
6848 if (tc == '.') { /* Precision */
6849 tc = *fmt++;
6850 if (tc == '*') { /* Precision from an argument */
6851 prec = va_arg(arp, int);
6852 tc = *fmt++;
6853 } else {
6854 prec = 0;
6855 while (IsDigit(tc)) { /* Precision */
6856 prec = prec * 10 + tc - '0';
6857 tc = *fmt++;
6858 }
6859 }
6860 }
6861 if (tc == 'l') { /* Size: long int */
6862 f |= 4; tc = *fmt++;
6863#if FF_PRINT_LLI && FF_INTDEF == 2
6864 if (tc == 'l') { /* Size: long long int */
6865 f |= 8; tc = *fmt++;
6866 }
6867#endif
6868 }
6869 if (tc == 0) break; /* End of format string */
6870 switch (tc) { /* Atgument type is... */
6871 case 'b': /* Unsigned binary */
6872 r = 2; break;
6873 case 'o': /* Unsigned octal */
6874 r = 8; break;
6875 case 'd': /* Signed decimal */
6876 case 'u': /* Unsigned decimal */
6877 r = 10; break;
6878 case 'x': /* Unsigned hexdecimal (lower case) */
6879 case 'X': /* Unsigned hexdecimal (upper case) */
6880 r = 16; break;
6881 case 'c': /* Character */
6882 putc_bfd(&pb, (TCHAR)va_arg(arp, int));
6883 continue;
6884 case 's': /* String */
6885 tp = va_arg(arp, TCHAR*); /* Get a pointer argument */
6886 if (!tp) tp = &nul; /* Null ptr generates a null string */
6887 for (j = 0; tp[j]; j++) ; /* j = tcslen(tp) */
6888 if (prec >= 0 && j > (UINT)prec) j = prec; /* Limited length of string body */
6889 for ( ; !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */
6890 while (*tp && prec--) putc_bfd(&pb, *tp++); /* Body */
6891 while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */
6892 continue;
6893#if FF_PRINT_FLOAT && FF_INTDEF == 2
6894 case 'f': /* Floating point (decimal) */
6895 case 'e': /* Floating point (e) */
6896 case 'E': /* Floating point (E) */
6897 ftoa(str, va_arg(arp, double), prec, tc); /* Make a flaoting point string */
6898 for (j = strlen(str); !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */
6899 for (i = 0; str[i]; putc_bfd(&pb, str[i++])) ; /* Body */
6900 while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */
6901 continue;
6902#endif
6903 default: /* Unknown type (pass-through) */
6904 putc_bfd(&pb, tc); continue;
6905 }
6906
6907 /* Get an integer argument and put it in numeral */
6908#if FF_PRINT_LLI && FF_INTDEF == 2
6909 if (f & 8) { /* long long argument? */
6910 v = (QWORD)va_arg(arp, LONGLONG);
6911 } else {
6912 if (f & 4) { /* long argument? */
6913 v = (tc == 'd') ? (QWORD)(LONGLONG)va_arg(arp, long) : (QWORD)va_arg(arp, unsigned long);
6914 } else { /* int/short/char argument */
6915 v = (tc == 'd') ? (QWORD)(LONGLONG)va_arg(arp, int) : (QWORD)va_arg(arp, unsigned int);
6916 }
6917 }
6918 if (tc == 'd' && (v & 0x8000000000000000)) { /* Negative value? */
6919 v = 0 - v; f |= 1;
6920 }
6921#else
6922 if (f & 4) { /* long argument? */
6923 v = (DWORD)va_arg(arp, long);
6924 } else { /* int/short/char argument */
6925 v = (tc == 'd') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int);
6926 }
6927 if (tc == 'd' && (v & 0x80000000)) { /* Negative value? */
6928 v = 0 - v; f |= 1;
6929 }
6930#endif
6931 i = 0;
6932 do { /* Make an integer number string */
6933 d = (char)(v % r); v /= r;
6934 if (d > 9) d += (tc == 'x') ? 0x27 : 0x07;
6935 str[i++] = d + '0';
6936 } while (v && i < SZ_NUM_BUF);
6937 if (f & 1) str[i++] = '-'; /* Sign */
6938 /* Write it */
6939 for (j = i; !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */
6940 do putc_bfd(&pb, (TCHAR)str[--i]); while (i); /* Body */
6941 while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */
6942 }
6943
6944 va_end(arp);
6945
6946 return putc_flush(&pb);
6947}
static uint32_t d
Definition Common.c:39
static uint32_t f
Definition Common.c:41
static void putc_bfd(putbuff *pb, TCHAR c)
Definition ff.c:6488
static int putc_flush(putbuff *pb)
Definition ff.c:6619
#define IsDigit(c)
Definition ff.c:50
#define SZ_NUM_BUF
Definition ff.c:6465
static void putc_init(putbuff *pb, FIL *fp)
Definition ff.c:6632
Definition ff.c:6473

◆ f_putc()

int f_putc ( TCHAR  c,
FIL fp 
)

Definition at line 6640 of file ff.c.

6644{
6645 putbuff pb;
6646
6647
6648 putc_init(&pb, fp);
6649 putc_bfd(&pb, c); /* Put the character */
6650 return putc_flush(&pb);
6651}
static uint32_t c
Definition Common.c:38

◆ f_puts()

int f_puts ( const TCHAR str,
FIL cp 
)

Definition at line 6660 of file ff.c.

6664{
6665 putbuff pb;
6666
6667
6668 putc_init(&pb, fp);
6669 while (*str) putc_bfd(&pb, *str++); /* Put the string */
6670 return putc_flush(&pb);
6671}

◆ f_read()

FRESULT f_read ( FIL fp,
void *  buff,
UINT  btr,
UINT br 
)

Definition at line 3850 of file ff.c.

3856{
3857 FRESULT res;
3858 FATFS *fs;
3859 DWORD clst;
3860 LBA_t sect;
3861 FSIZE_t remain;
3862 UINT rcnt, cc, csect;
3863 BYTE *rbuff = (BYTE*)buff;
3864
3865
3866 *br = 0; /* Clear read byte counter */
3867 res = validate(&fp->obj, &fs); /* Check validity of the file object */
3868 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
3869 if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
3870 remain = fp->obj.objsize - fp->fptr;
3871 if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
3872
3873 for ( ; btr > 0; btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { /* Repeat until btr bytes read */
3874 if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
3875 csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */
3876 if (csect == 0) { /* On the cluster boundary? */
3877 if (fp->fptr == 0) { /* On the top of the file? */
3878 clst = fp->obj.sclust; /* Follow cluster chain from the origin */
3879 } else { /* Middle or end of the file */
3880#if FF_USE_FASTSEEK
3881 if (fp->cltbl) {
3882 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
3883 } else
3884#endif
3885 {
3886 clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */
3887 }
3888 }
3889 if (clst < 2) ABORT(fs, FR_INT_ERR);
3890 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
3891 fp->clust = clst; /* Update current cluster */
3892 }
3893 sect = clst2sect(fs, fp->clust); /* Get current sector */
3894 if (sect == 0) ABORT(fs, FR_INT_ERR);
3895 sect += csect;
3896 cc = btr / SS(fs); /* When remaining bytes >= sector size, */
3897 if (cc > 0) { /* Read maximum contiguous sectors directly */
3898 if (csect + cc > fs->csize) { /* Clip at cluster boundary */
3899 cc = fs->csize - csect;
3900 }
3901 if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
3902#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
3903#if FF_FS_TINY
3904 if (fs->wflag && fs->winsect - sect < cc) {
3905 memcpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs));
3906 }
3907#else
3908 if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) {
3909 memcpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs));
3910 }
3911#endif
3912#endif
3913 rcnt = SS(fs) * cc; /* Number of bytes transferred */
3914 continue;
3915 }
3916#if !FF_FS_TINY
3917 if (fp->sect != sect) { /* Load data sector if not in cache */
3918#if !FF_FS_READONLY
3919 if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
3920 if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
3921 fp->flag &= (BYTE)~FA_DIRTY;
3922 }
3923#endif
3924 if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
3925 }
3926#endif
3927 fp->sect = sect;
3928 }
3929 rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes remains in the sector */
3930 if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */
3931#if FF_FS_TINY
3932 if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */
3933 memcpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
3934#else
3935 memcpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
3936#endif
3937 }
3938
3939 LEAVE_FF(fs, FR_OK);
3940}

◆ f_readdir()

FRESULT f_readdir ( DIR dp,
FILINFO fno 
)

Definition at line 4627 of file ff.c.

4631{
4632 FRESULT res;
4633 FATFS *fs;
4635
4636
4637 res = validate(&dp->obj, &fs); /* Check validity of the directory object */
4638 if (res == FR_OK) {
4639 if (!fno) {
4640 res = dir_sdi(dp, 0); /* Rewind the directory object */
4641 } else {
4642 INIT_NAMBUF(fs);
4643 res = DIR_READ_FILE(dp); /* Read an item */
4644 if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
4645 if (res == FR_OK) { /* A valid entry is found */
4646 get_fileinfo(dp, fno); /* Get the object information */
4647 res = dir_next(dp, 0); /* Increment index for next */
4648 if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory now */
4649 }
4650 FREE_NAMBUF();
4651 }
4652 }
4653 LEAVE_FF(fs, res);
4654}
static void get_fileinfo(DIR *dp, FILINFO *fno)
Definition ff.c:2586
static FRESULT dir_next(DIR *dp, int stretch)
Definition ff.c:1714
#define DIR_READ_FILE(dp)
Definition ff.c:2272

◆ f_rename()

FRESULT f_rename ( const TCHAR path_old,
const TCHAR path_new 
)

Definition at line 5070 of file ff.c.

5074{
5075 FRESULT res;
5076 DIR djo, djn;
5077 FATFS *fs;
5078 BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir;
5079 LBA_t sect;
5081
5082
5083 get_ldnumber(&path_new); /* Snip the drive number of new name off */
5084 res = mount_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */
5085 if (res == FR_OK) {
5086 djo.obj.fs = fs;
5087 INIT_NAMBUF(fs);
5088 res = follow_path(&djo, path_old); /* Check old object */
5089 if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */
5090#if FF_FS_LOCK != 0
5091 if (res == FR_OK) {
5092 res = chk_lock(&djo, 2);
5093 }
5094#endif
5095 if (res == FR_OK) { /* Object to be renamed is found */
5096#if FF_FS_EXFAT
5097 if (fs->fs_type == FS_EXFAT) { /* At exFAT volume */
5098 BYTE nf, nn;
5099 WORD nh;
5100
5101 memcpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */
5102 memcpy(&djn, &djo, sizeof djo);
5103 res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */
5104 if (res == FR_OK) { /* Is new name already in use by any other object? */
5105 res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
5106 }
5107 if (res == FR_NO_FILE) { /* It is a valid path and no name collision */
5108 res = dir_register(&djn); /* Register the new entry */
5109 if (res == FR_OK) {
5110 nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName];
5111 nh = ld_word(fs->dirbuf + XDIR_NameHash);
5112 memcpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */
5113 fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn;
5114 st_word(fs->dirbuf + XDIR_NameHash, nh);
5115 if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */
5116/* Start of critical section where an interruption can cause a cross-link */
5117 res = store_xdir(&djn);
5118 }
5119 }
5120 } else
5121#endif
5122 { /* At FAT/FAT32 volume */
5123 memcpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */
5124 memcpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */
5125 res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */
5126 if (res == FR_OK) { /* Is new name already in use by any other object? */
5127 res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
5128 }
5129 if (res == FR_NO_FILE) { /* It is a valid path and no name collision */
5130 res = dir_register(&djn); /* Register the new entry */
5131 if (res == FR_OK) {
5132 dir = djn.dir; /* Copy directory entry of the object except name */
5133 memcpy(dir + 13, buf + 13, SZDIRE - 13);
5134 dir[DIR_Attr] = buf[DIR_Attr];
5135 if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */
5136 fs->wflag = 1;
5137 if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) { /* Update .. entry in the sub-directory if needed */
5138 sect = clst2sect(fs, ld_clust(fs, dir));
5139 if (sect == 0) {
5140 res = FR_INT_ERR;
5141 } else {
5142/* Start of critical section where an interruption can cause a cross-link */
5143 res = move_window(fs, sect);
5144 dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */
5145 if (res == FR_OK && dir[1] == '.') {
5146 st_clust(fs, dir, djn.obj.sclust);
5147 fs->wflag = 1;
5148 }
5149 }
5150 }
5151 }
5152 }
5153 }
5154 if (res == FR_OK) {
5155 res = dir_remove(&djo); /* Remove old entry */
5156 if (res == FR_OK) {
5157 res = sync_fs(fs);
5158 }
5159 }
5160/* End of the critical section */
5161 }
5162 FREE_NAMBUF();
5163 }
5164
5165 LEAVE_FF(fs, res);
5166}
static void st_word(BYTE *ptr, WORD val)
Definition ff.c:652
#define XDIR_NumSec
Definition ff.c:170
#define XDIR_NumName
Definition ff.c:182
static FRESULT dir_remove(DIR *dp)
Definition ff.c:2540
#define XDIR_NameHash
Definition ff.c:183
unsigned short WORD
Definition ff.h:60
DWORD dptr
Definition ff.h:230

◆ f_setcp()

FRESULT f_setcp ( WORD  cp)

◆ f_setlabel()

FRESULT f_setlabel ( const TCHAR label)

◆ f_stat()

FRESULT f_stat ( const TCHAR path,
FILINFO fno 
)

Definition at line 4715 of file ff.c.

4719{
4720 FRESULT res;
4721 DIR dj;
4723
4724
4725 /* Get logical drive */
4726 res = mount_volume(&path, &dj.obj.fs, 0);
4727 if (res == FR_OK) {
4728 INIT_NAMBUF(dj.obj.fs);
4729 res = follow_path(&dj, path); /* Follow the file path */
4730 if (res == FR_OK) { /* Follow completed */
4731 if (dj.fn[NSFLAG] & NS_NONAME) { /* It is origin directory */
4732 res = FR_INVALID_NAME;
4733 } else { /* Found an object */
4734 if (fno) get_fileinfo(&dj, fno);
4735 }
4736 }
4737 FREE_NAMBUF();
4738 }
4739
4740 LEAVE_FF(dj.obj.fs, res);
4741}

◆ f_sync()

FRESULT f_sync ( FIL fp)

Definition at line 4071 of file ff.c.

4074{
4075 FRESULT res;
4076 FATFS *fs;
4077 DWORD tm;
4078 BYTE *dir;
4079
4080
4081 res = validate(&fp->obj, &fs); /* Check validity of the file object */
4082 if (res == FR_OK) {
4083 if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */
4084#if !FF_FS_TINY
4085 if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */
4086 if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
4087 fp->flag &= (BYTE)~FA_DIRTY;
4088 }
4089#endif
4090 /* Update the directory entry */
4091 tm = GET_FATTIME(); /* Modified time */
4092#if FF_FS_EXFAT
4093 if (fs->fs_type == FS_EXFAT) {
4094 res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */
4095 if (res == FR_OK) {
4096 res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */
4097 }
4098 if (res == FR_OK) {
4099 DIR dj;
4101
4102 INIT_NAMBUF(fs);
4103 res = load_obj_xdir(&dj, &fp->obj); /* Load directory entry block */
4104 if (res == FR_OK) {
4105 fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */
4106 fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */
4107 st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); /* Update start cluster */
4108 st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); /* Update file size */
4109 st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); /* (FatFs does not support Valid File Size feature) */
4110 st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */
4111 fs->dirbuf[XDIR_ModTime10] = 0;
4112 st_dword(fs->dirbuf + XDIR_AccTime, 0);
4113 res = store_xdir(&dj); /* Restore it to the directory */
4114 if (res == FR_OK) {
4115 res = sync_fs(fs);
4116 fp->flag &= (BYTE)~FA_MODIFIED;
4117 }
4118 }
4119 FREE_NAMBUF();
4120 }
4121 } else
4122#endif
4123 {
4124 res = move_window(fs, fp->dir_sect);
4125 if (res == FR_OK) {
4126 dir = fp->dir_ptr;
4127 dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */
4128 st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */
4129 st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */
4130 st_dword(dir + DIR_ModTime, tm); /* Update modified time */
4131 st_word(dir + DIR_LstAccDate, 0);
4132 fs->wflag = 1;
4133 res = sync_fs(fs); /* Restore it to the directory */
4134 fp->flag &= (BYTE)~FA_MODIFIED;
4135 }
4136 }
4137 }
4138 }
4139
4140 LEAVE_FF(fs, res);
4141}
#define XDIR_ModTime10
Definition ff.c:177
#define XDIR_AccTime
Definition ff.c:175
#define DIR_LstAccDate
Definition ff.c:156

◆ f_truncate()

FRESULT f_truncate ( FIL fp)

Definition at line 4842 of file ff.c.

4845{
4846 FRESULT res;
4847 FATFS *fs;
4848 DWORD ncl;
4849
4850
4851 res = validate(&fp->obj, &fs); /* Check validity of the file object */
4852 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
4853 if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
4854
4855 if (fp->fptr < fp->obj.objsize) { /* Process when fptr is not on the eof */
4856 if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */
4857 res = remove_chain(&fp->obj, fp->obj.sclust, 0);
4858 fp->obj.sclust = 0;
4859 } else { /* When truncate a part of the file, remove remaining clusters */
4860 ncl = get_fat(&fp->obj, fp->clust);
4861 res = FR_OK;
4862 if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
4863 if (ncl == 1) res = FR_INT_ERR;
4864 if (res == FR_OK && ncl < fs->n_fatent) {
4865 res = remove_chain(&fp->obj, ncl, fp->clust);
4866 }
4867 }
4868 fp->obj.objsize = fp->fptr; /* Set file size to current read/write point */
4869 fp->flag |= FA_MODIFIED;
4870#if !FF_FS_TINY
4871 if (res == FR_OK && (fp->flag & FA_DIRTY)) {
4872 if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
4873 res = FR_DISK_ERR;
4874 } else {
4875 fp->flag &= (BYTE)~FA_DIRTY;
4876 }
4877 }
4878#endif
4879 if (res != FR_OK) ABORT(fs, res);
4880 }
4881
4882 LEAVE_FF(fs, res);
4883}

◆ f_unlink()

FRESULT f_unlink ( const TCHAR path)

Definition at line 4892 of file ff.c.

4895{
4896 FRESULT res;
4897 DIR dj, sdj;
4898 DWORD dclst = 0;
4899 FATFS *fs;
4900#if FF_FS_EXFAT
4901 FFOBJID obj;
4902#endif
4904
4905
4906 /* Get logical drive */
4907 res = mount_volume(&path, &fs, FA_WRITE);
4908 if (res == FR_OK) {
4909 dj.obj.fs = fs;
4910 INIT_NAMBUF(fs);
4911 res = follow_path(&dj, path); /* Follow the file path */
4912 if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) {
4913 res = FR_INVALID_NAME; /* Cannot remove dot entry */
4914 }
4915#if FF_FS_LOCK != 0
4916 if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */
4917#endif
4918 if (res == FR_OK) { /* The object is accessible */
4919 if (dj.fn[NSFLAG] & NS_NONAME) {
4920 res = FR_INVALID_NAME; /* Cannot remove the origin directory */
4921 } else {
4922 if (dj.obj.attr & AM_RDO) {
4923 res = FR_DENIED; /* Cannot remove R/O object */
4924 }
4925 }
4926 if (res == FR_OK) {
4927#if FF_FS_EXFAT
4928 obj.fs = fs;
4929 if (fs->fs_type == FS_EXFAT) {
4930 init_alloc_info(fs, &obj);
4931 dclst = obj.sclust;
4932 } else
4933#endif
4934 {
4935 dclst = ld_clust(fs, dj.dir);
4936 }
4937 if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory? */
4938#if FF_FS_RPATH != 0
4939 if (dclst == fs->cdir) { /* Is it the current directory? */
4940 res = FR_DENIED;
4941 } else
4942#endif
4943 {
4944 sdj.obj.fs = fs; /* Open the sub-directory */
4945 sdj.obj.sclust = dclst;
4946#if FF_FS_EXFAT
4947 if (fs->fs_type == FS_EXFAT) {
4948 sdj.obj.objsize = obj.objsize;
4949 sdj.obj.stat = obj.stat;
4950 }
4951#endif
4952 res = dir_sdi(&sdj, 0);
4953 if (res == FR_OK) {
4954 res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */
4955 if (res == FR_OK) res = FR_DENIED; /* Not empty? */
4956 if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
4957 }
4958 }
4959 }
4960 }
4961 if (res == FR_OK) {
4962 res = dir_remove(&dj); /* Remove the directory entry */
4963 if (res == FR_OK && dclst != 0) { /* Remove the cluster chain if exist */
4964#if FF_FS_EXFAT
4965 res = remove_chain(&obj, dclst, 0);
4966#else
4967 res = remove_chain(&dj.obj, dclst, 0);
4968#endif
4969 }
4970 if (res == FR_OK) res = sync_fs(fs);
4971 }
4972 }
4973 FREE_NAMBUF();
4974 }
4975
4976 LEAVE_FF(fs, res);
4977}

◆ f_utime()

FRESULT f_utime ( const TCHAR path,
const FILINFO fno 
)

◆ f_write()

FRESULT f_write ( FIL fp,
const void *  buff,
UINT  btw,
UINT bw 
)

Definition at line 3950 of file ff.c.

3956{
3957 FRESULT res;
3958 FATFS *fs;
3959 DWORD clst;
3960 LBA_t sect;
3961 UINT wcnt, cc, csect;
3962 const BYTE *wbuff = (const BYTE*)buff;
3963
3964
3965 *bw = 0; /* Clear write byte counter */
3966 res = validate(&fp->obj, &fs); /* Check validity of the file object */
3967 if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
3968 if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
3969
3970 /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
3971 if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
3972 btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr);
3973 }
3974
3975 for ( ; btw > 0; btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) { /* Repeat until all data written */
3976 if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
3977 csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */
3978 if (csect == 0) { /* On the cluster boundary? */
3979 if (fp->fptr == 0) { /* On the top of the file? */
3980 clst = fp->obj.sclust; /* Follow from the origin */
3981 if (clst == 0) { /* If no cluster is allocated, */
3982 clst = create_chain(&fp->obj, 0); /* create a new cluster chain */
3983 }
3984 } else { /* On the middle or end of the file */
3985#if FF_USE_FASTSEEK
3986 if (fp->cltbl) {
3987 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
3988 } else
3989#endif
3990 {
3991 clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */
3992 }
3993 }
3994 if (clst == 0) break; /* Could not allocate a new cluster (disk full) */
3995 if (clst == 1) ABORT(fs, FR_INT_ERR);
3996 if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
3997 fp->clust = clst; /* Update current cluster */
3998 if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */
3999 }
4000#if FF_FS_TINY
4001 if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */
4002#else
4003 if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
4004 if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
4005 fp->flag &= (BYTE)~FA_DIRTY;
4006 }
4007#endif
4008 sect = clst2sect(fs, fp->clust); /* Get current sector */
4009 if (sect == 0) ABORT(fs, FR_INT_ERR);
4010 sect += csect;
4011 cc = btw / SS(fs); /* When remaining bytes >= sector size, */
4012 if (cc > 0) { /* Write maximum contiguous sectors directly */
4013 if (csect + cc > fs->csize) { /* Clip at cluster boundary */
4014 cc = fs->csize - csect;
4015 }
4016 if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
4017#if FF_FS_MINIMIZE <= 2
4018#if FF_FS_TINY
4019 if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
4020 memcpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs));
4021 fs->wflag = 0;
4022 }
4023#else
4024 if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
4025 memcpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs));
4026 fp->flag &= (BYTE)~FA_DIRTY;
4027 }
4028#endif
4029#endif
4030 wcnt = SS(fs) * cc; /* Number of bytes transferred */
4031 continue;
4032 }
4033#if FF_FS_TINY
4034 if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */
4035 if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);
4036 fs->winsect = sect;
4037 }
4038#else
4039 if (fp->sect != sect && /* Fill sector cache with file data */
4040 fp->fptr < fp->obj.objsize &&
4041 disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
4042 ABORT(fs, FR_DISK_ERR);
4043 }
4044#endif
4045 fp->sect = sect;
4046 }
4047 wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes remains in the sector */
4048 if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */
4049#if FF_FS_TINY
4050 if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */
4051 memcpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */
4052 fs->wflag = 1;
4053#else
4054 memcpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */
4055 fp->flag |= FA_DIRTY;
4056#endif
4057 }
4058
4059 fp->flag |= FA_MODIFIED; /* Set file change flag */
4060
4061 LEAVE_FF(fs, FR_OK);
4062}
static FRESULT sync_window(FATFS *fs)
Definition ff.c:1025

◆ ff_memalloc()

void * ff_memalloc ( UINT  msize)

Definition at line 16 of file ffsystem.c.

19{
20 return malloc(msize); /* Allocate a new memory block with POSIX API */
21}

◆ ff_memfree()

void ff_memfree ( void *  mblock)

Definition at line 28 of file ffsystem.c.

31{
32 free(mblock); /* Free the memory block with POSIX API */
33}

◆ ff_oem2uni()

WCHAR ff_oem2uni ( WCHAR  oem,
WORD  cp 
)

Definition at line 15244 of file ffunicode.c.

15248{
15249 WCHAR c = 0;
15250 const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
15251
15252
15253 if (oem < 0x80) { /* ASCII? */
15254 c = oem;
15255
15256 } else { /* Extended char */
15257 if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
15258 if (oem < 0x100) c = p[oem - 0x80];
15259 }
15260 }
15261
15262 return c;
15263}
#define FF_CODE_PAGE
Definition ffconf.h:90
#define CVTBL(tbl, cp)
Definition ffunicode.c:31

◆ ff_uni2oem()

WCHAR ff_uni2oem ( DWORD  uni,
WORD  cp 
)

Definition at line 15222 of file ffunicode.c.

15226{
15227 WCHAR c = 0;
15228 const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
15229
15230
15231 if (uni < 0x80) { /* ASCII? */
15232 c = (WCHAR)uni;
15233
15234 } else { /* Non-ASCII */
15235 if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
15236 for (c = 0; c < 0x80 && uni != p[c]; c++) ;
15237 c = (c + 0x80) & 0xFF;
15238 }
15239 }
15240
15241 return c;
15242}

◆ ff_wtoupper()

DWORD ff_wtoupper ( DWORD  uni)

Definition at line 15464 of file ffunicode.c.

15467{
15468 const WORD *p;
15469 WORD uc, bc, nc, cmd;
15470 static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */
15471 /* Basic Latin */
15472 0x0061,0x031A,
15473 /* Latin-1 Supplement */
15474 0x00E0,0x0317,
15475 0x00F8,0x0307,
15476 0x00FF,0x0001,0x0178,
15477 /* Latin Extended-A */
15478 0x0100,0x0130,
15479 0x0132,0x0106,
15480 0x0139,0x0110,
15481 0x014A,0x012E,
15482 0x0179,0x0106,
15483 /* Latin Extended-B */
15484 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
15485 0x01CD,0x0110,
15486 0x01DD,0x0001,0x018E,
15487 0x01DE,0x0112,
15488 0x01F3,0x0003,0x01F1,0x01F4,0x01F4,
15489 0x01F8,0x0128,
15490 0x0222,0x0112,
15491 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241,
15492 0x0246,0x010A,
15493 /* IPA Extensions */
15494 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
15495 /* Greek, Coptic */
15496 0x037B,0x0003,0x03FD,0x03FE,0x03FF,
15497 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A,
15498 0x03B1,0x0311,
15499 0x03C2,0x0002,0x03A3,0x03A3,
15500 0x03C4,0x0308,
15501 0x03CC,0x0003,0x038C,0x038E,0x038F,
15502 0x03D8,0x0118,
15503 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
15504 /* Cyrillic */
15505 0x0430,0x0320,
15506 0x0450,0x0710,
15507 0x0460,0x0122,
15508 0x048A,0x0136,
15509 0x04C1,0x010E,
15510 0x04CF,0x0001,0x04C0,
15511 0x04D0,0x0144,
15512 /* Armenian */
15513 0x0561,0x0426,
15514
15515 0x0000 /* EOT */
15516 };
15517 static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */
15518 /* Phonetic Extensions */
15519 0x1D7D,0x0001,0x2C63,
15520 /* Latin Extended Additional */
15521 0x1E00,0x0196,
15522 0x1EA0,0x015A,
15523 /* Greek Extended */
15524 0x1F00,0x0608,
15525 0x1F10,0x0606,
15526 0x1F20,0x0608,
15527 0x1F30,0x0608,
15528 0x1F40,0x0606,
15529 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F,
15530 0x1F60,0x0608,
15531 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
15532 0x1F80,0x0608,
15533 0x1F90,0x0608,
15534 0x1FA0,0x0608,
15535 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
15536 0x1FCC,0x0001,0x1FC3,
15537 0x1FD0,0x0602,
15538 0x1FE0,0x0602,
15539 0x1FE5,0x0001,0x1FEC,
15540 0x1FF3,0x0001,0x1FFC,
15541 /* Letterlike Symbols */
15542 0x214E,0x0001,0x2132,
15543 /* Number forms */
15544 0x2170,0x0210,
15545 0x2184,0x0001,0x2183,
15546 /* Enclosed Alphanumerics */
15547 0x24D0,0x051A,
15548 0x2C30,0x042F,
15549 /* Latin Extended-C */
15550 0x2C60,0x0102,
15551 0x2C67,0x0106, 0x2C75,0x0102,
15552 /* Coptic */
15553 0x2C80,0x0164,
15554 /* Georgian Supplement */
15555 0x2D00,0x0826,
15556 /* Full-width */
15557 0xFF41,0x031A,
15558
15559 0x0000 /* EOT */
15560 };
15561
15562
15563 if (uni < 0x10000) { /* Is it in BMP? */
15564 uc = (WORD)uni;
15565 p = uc < 0x1000 ? cvt1 : cvt2;
15566 for (;;) {
15567 bc = *p++; /* Get the block base */
15568 if (bc == 0 || uc < bc) break; /* Not matched? */
15569 nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
15570 if (uc < bc + nc) { /* In the block? */
15571 switch (cmd) {
15572 case 0: uc = p[uc - bc]; break; /* Table conversion */
15573 case 1: uc -= (uc - bc) & 1; break; /* Case pairs */
15574 case 2: uc -= 16; break; /* Shift -16 */
15575 case 3: uc -= 32; break; /* Shift -32 */
15576 case 4: uc -= 48; break; /* Shift -48 */
15577 case 5: uc -= 26; break; /* Shift -26 */
15578 case 6: uc += 8; break; /* Shift +8 */
15579 case 7: uc -= 80; break; /* Shift -80 */
15580 case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */
15581 }
15582 break;
15583 }
15584 if (cmd == 0) p += nc; /* Skip table if needed */
15585 }
15586 uni = uc;
15587 }
15588
15589 return uni;
15590}
static ft_void_t ft_uint32_t * cmd
Definition FT_Gpu_Hal.h:184