ReactOS 0.4.15-dev-8127-g6338913
ff.c File Reference
#include "ff.h"
#include "diskio.h"
Include dependency graph for ff.c:

Go to the source code of this file.

Macros

#define ENTER_FF(fs)
 
#define LEAVE_FF(fs, res)   return res
 
#define ABORT(fs, res)   { fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
 
#define SS(fs)   ((UINT)_MAX_SS) /* Fixed sector size */
 
#define GET_FATTIME()   get_fattime()
 
#define _DF1S   0
 
#define _EXCVT
 
#define IsUpper(c)   (((c)>='A')&&((c)<='Z'))
 
#define IsLower(c)   (((c)>='a')&&((c)<='z'))
 
#define IsDigit(c)   (((c)>='0')&&((c)<='9'))
 
#define IsDBCS1(c)   0
 
#define IsDBCS2(c)   0
 
#define NSFLAG   11 /* Index of name status byte in fn[] */
 
#define NS_LOSS   0x01 /* Out of 8.3 format */
 
#define NS_LFN   0x02 /* Force to create LFN entry */
 
#define NS_LAST   0x04 /* Last segment */
 
#define NS_BODY   0x08 /* Lower case flag (body) */
 
#define NS_EXT   0x10 /* Lower case flag (ext) */
 
#define NS_DOT   0x20 /* Dot entry */
 
#define MIN_FAT16   4086U /* Minimum number of clusters of FAT16 */
 
#define MIN_FAT32   65526U /* Minimum number of clusters of FAT32 */
 
#define BS_jmpBoot   0 /* x86 jump instruction (3) */
 
#define BS_OEMName   3 /* OEM name (8) */
 
#define BPB_BytsPerSec   11 /* Sector size [byte] (2) */
 
#define BPB_SecPerClus   13 /* Cluster size [sector] (1) */
 
#define BPB_RsvdSecCnt   14 /* Size of reserved area [sector] (2) */
 
#define BPB_NumFATs   16 /* Number of FAT copies (1) */
 
#define BPB_RootEntCnt   17 /* Number of root directory entries for FAT12/16 (2) */
 
#define BPB_TotSec16   19 /* Volume size [sector] (2) */
 
#define BPB_Media   21 /* Media descriptor (1) */
 
#define BPB_FATSz16   22 /* FAT size [sector] (2) */
 
#define BPB_SecPerTrk   24 /* Track size [sector] (2) */
 
#define BPB_NumHeads   26 /* Number of heads (2) */
 
#define BPB_HiddSec   28 /* Number of special hidden sectors (4) */
 
#define BPB_TotSec32   32 /* Volume size [sector] (4) */
 
#define BS_DrvNum   36 /* Physical drive number (1) */
 
#define BS_NTres   37 /* Error flag (1) */
 
#define BS_BootSig   38 /* Extended boot signature (1) */
 
#define BS_VolID   39 /* Volume serial number (4) */
 
#define BS_VolLab   43 /* Volume label (8) */
 
#define BS_FilSysType   54 /* File system type (1) */
 
#define BPB_FATSz32   36 /* FAT size [sector] (4) */
 
#define BPB_ExtFlags   40 /* Extended flags (2) */
 
#define BPB_FSVer   42 /* File system version (2) */
 
#define BPB_RootClus   44 /* Root directory first cluster (4) */
 
#define BPB_FSInfo   48 /* Offset of FSINFO sector (2) */
 
#define BPB_BkBootSec   50 /* Offset of backup boot sector (2) */
 
#define BS_DrvNum32   64 /* Physical drive number (1) */
 
#define BS_NTres32   65 /* Error flag (1) */
 
#define BS_BootSig32   66 /* Extended boot signature (1) */
 
#define BS_VolID32   67 /* Volume serial number (4) */
 
#define BS_VolLab32   71 /* Volume label (8) */
 
#define BS_FilSysType32   82 /* File system type (1) */
 
#define FSI_LeadSig   0 /* FSI: Leading signature (4) */
 
#define FSI_StrucSig   484 /* FSI: Structure signature (4) */
 
#define FSI_Free_Count   488 /* FSI: Number of free clusters (4) */
 
#define FSI_Nxt_Free   492 /* FSI: Last allocated cluster (4) */
 
#define MBR_Table   446 /* MBR: Partition table offset (2) */
 
#define SZ_PTE   16 /* MBR: Size of a partition table entry */
 
#define BS_55AA   510 /* Signature word (2) */
 
#define DIR_Name   0 /* Short file name (11) */
 
#define DIR_Attr   11 /* Attribute (1) */
 
#define DIR_NTres   12 /* Lower case 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) */
 
#define DIR_FstClusLO   26 /* Lower 16-bit of first cluster (2) */
 
#define DIR_FileSize   28 /* File size (4) */
 
#define LDIR_Ord   0 /* LFN entry order and LLE flag (1) */
 
#define LDIR_Attr   11 /* LFN attribute (1) */
 
#define LDIR_Type   12 /* LFN type (1) */
 
#define LDIR_Chksum   13 /* Checksum of corresponding SFN entry */
 
#define LDIR_FstClusLO   26 /* Must be zero (0) */
 
#define SZ_DIRE   32 /* Size of a directory entry */
 
#define LLEF   0x40 /* Last long entry flag in LDIR_Ord */
 
#define DDEM   0xE5 /* Deleted directory entry mark at DIR_Name[0] */
 
#define RDDEM   0x05 /* Replacement of the character collides with DDEM */
 
#define DEFINE_NAMEBUF   BYTE sfn[12]; WCHAR lbuf[_MAX_LFN + 1]
 
#define INIT_BUF(dobj)   { (dobj).fn = sfn; (dobj).lfn = lbuf; }
 
#define FREE_BUF()
 
#define N_ROOTDIR12   224 /* Number of root directory entries for FAT12 */
 
#define N_ROOTDIR16   512 /* Number of root directory entries for FAT16 */
 
#define N_FATS   2 /* Number of FATs (1 or 2) */
 

Functions

static void mem_cpy (void *dst, const void *src, UINT cnt)
 
static void mem_set (void *dst, int val, UINT cnt)
 
static int mem_cmp (const void *dst, const void *src, UINT cnt)
 
static int chk_chr (const char *str, int chr)
 
static FRESULT sync_window (FATFS *fs)
 
static FRESULT move_window (FATFS *fs, DWORD sector)
 
static FRESULT sync_fs (FATFS *fs)
 
DWORD clust2sect (FATFS *fs, DWORD clst)
 
DWORD get_fat (FATFS *fs, DWORD clst)
 
FRESULT put_fat (FATFS *fs, DWORD clst, DWORD val)
 
static FRESULT remove_chain (FATFS *fs, DWORD clst)
 
static DWORD create_chain (FATFS *fs, DWORD clst)
 
static FRESULT dir_sdi (DIR *dp, UINT idx)
 
static FRESULT dir_next (DIR *dp, int stretch)
 
static FRESULT dir_alloc (DIR *dp, UINT nent)
 
static DWORD ld_clust (FATFS *fs, const BYTE *dir)
 
static void st_clust (BYTE *dir, DWORD cl)
 
static int cmp_lfn (WCHAR *lfnbuf, BYTE *dir)
 
static int pick_lfn (WCHAR *lfnbuf, BYTE *dir)
 
static void fit_lfn (const WCHAR *lfnbuf, BYTE *dir, BYTE ord, BYTE sum)
 
static void gen_numname (BYTE *dst, const BYTE *src, const WCHAR *lfn, UINT seq)
 
static BYTE sum_sfn (const BYTE *dir)
 
static FRESULT dir_find (DIR *dp)
 
static FRESULT dir_read (DIR *dp, int vol)
 
static FRESULT dir_register (DIR *dp)
 
static FRESULT dir_remove (DIR *dp)
 
static void get_fileinfo (DIR *dp, FILINFO *fno)
 
static FRESULT create_name (DIR *dp, const TCHAR **path)
 
static FRESULT follow_path (DIR *dp, const TCHAR *path)
 
static int get_ldnumber (const TCHAR **path)
 
static BYTE check_fs (FATFS *fs, DWORD sect)
 
static FRESULT find_volume (FATFS **rfs, const TCHAR **path, BYTE wmode)
 
static FRESULT validate (void *obj)
 
FRESULT f_mount (FATFS *fs, const TCHAR *path, BYTE opt)
 
FRESULT f_open (FIL *fp, const TCHAR *path, BYTE mode)
 
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_sync (FIL *fp)
 
FRESULT f_close (FIL *fp)
 
FRESULT f_lseek (FIL *fp, DWORD ofs)
 
FRESULT f_opendir (DIR *dp, const TCHAR *path)
 
FRESULT f_closedir (DIR *dp)
 
FRESULT f_readdir (DIR *dp, FILINFO *fno)
 
FRESULT f_stat (const TCHAR *path, FILINFO *fno)
 
FRESULT f_getfree (const TCHAR *path, DWORD *nclst, FATFS **fatfs)
 
FRESULT f_truncate (FIL *fp)
 
FRESULT f_unlink (const TCHAR *path)
 
FRESULT f_mkdir (const TCHAR *path)
 
FRESULT f_chmod (const TCHAR *path, BYTE attr, BYTE mask)
 
FRESULT f_rename (const TCHAR *path_old, const TCHAR *path_new)
 
FRESULT f_utime (const TCHAR *path, const FILINFO *fno)
 
FRESULT f_getlabel (const TCHAR *path, TCHAR *label, DWORD *vsn)
 
FRESULT f_setlabel (const TCHAR *label)
 
FRESULT f_mkfs (const TCHAR *path, BYTE sfd, UINT au)
 

Variables

static FATFSFatFs [_VOLUMES]
 
static WORD Fsid
 
static const BYTE ExCvt [] = _EXCVT
 
static const BYTE LfnOfs [] = {1,3,5,7,9,14,16,18,20,22,24,28,30}
 

Macro Definition Documentation

◆ _DF1S

#define _DF1S   0

Definition at line 125 of file ff.c.

◆ _EXCVT

#define _EXCVT
Value:
{0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \
0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \
0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \
0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \
0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \
0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF}

Definition at line 126 of file ff.c.

◆ ABORT

#define ABORT (   fs,
  res 
)    { fp->err = (BYTE)(res); LEAVE_FF(fs, res); }

Definition at line 46 of file ff.c.

◆ BPB_BkBootSec

#define BPB_BkBootSec   50 /* Offset of backup boot sector (2) */

Definition at line 394 of file ff.c.

◆ BPB_BytsPerSec

#define BPB_BytsPerSec   11 /* Sector size [byte] (2) */

Definition at line 371 of file ff.c.

◆ BPB_ExtFlags

#define BPB_ExtFlags   40 /* Extended flags (2) */

Definition at line 390 of file ff.c.

◆ BPB_FATSz16

#define BPB_FATSz16   22 /* FAT size [sector] (2) */

Definition at line 378 of file ff.c.

◆ BPB_FATSz32

#define BPB_FATSz32   36 /* FAT size [sector] (4) */

Definition at line 389 of file ff.c.

◆ BPB_FSInfo

#define BPB_FSInfo   48 /* Offset of FSINFO sector (2) */

Definition at line 393 of file ff.c.

◆ BPB_FSVer

#define BPB_FSVer   42 /* File system version (2) */

Definition at line 391 of file ff.c.

◆ BPB_HiddSec

#define BPB_HiddSec   28 /* Number of special hidden sectors (4) */

Definition at line 381 of file ff.c.

◆ BPB_Media

#define BPB_Media   21 /* Media descriptor (1) */

Definition at line 377 of file ff.c.

◆ BPB_NumFATs

#define BPB_NumFATs   16 /* Number of FAT copies (1) */

Definition at line 374 of file ff.c.

◆ BPB_NumHeads

#define BPB_NumHeads   26 /* Number of heads (2) */

Definition at line 380 of file ff.c.

◆ BPB_RootClus

#define BPB_RootClus   44 /* Root directory first cluster (4) */

Definition at line 392 of file ff.c.

◆ BPB_RootEntCnt

#define BPB_RootEntCnt   17 /* Number of root directory entries for FAT12/16 (2) */

Definition at line 375 of file ff.c.

◆ BPB_RsvdSecCnt

#define BPB_RsvdSecCnt   14 /* Size of reserved area [sector] (2) */

Definition at line 373 of file ff.c.

◆ BPB_SecPerClus

#define BPB_SecPerClus   13 /* Cluster size [sector] (1) */

Definition at line 372 of file ff.c.

◆ BPB_SecPerTrk

#define BPB_SecPerTrk   24 /* Track size [sector] (2) */

Definition at line 379 of file ff.c.

◆ BPB_TotSec16

#define BPB_TotSec16   19 /* Volume size [sector] (2) */

Definition at line 376 of file ff.c.

◆ BPB_TotSec32

#define BPB_TotSec32   32 /* Volume size [sector] (4) */

Definition at line 382 of file ff.c.

◆ BS_55AA

#define BS_55AA   510 /* Signature word (2) */

Definition at line 407 of file ff.c.

◆ BS_BootSig

#define BS_BootSig   38 /* Extended boot signature (1) */

Definition at line 385 of file ff.c.

◆ BS_BootSig32

#define BS_BootSig32   66 /* Extended boot signature (1) */

Definition at line 397 of file ff.c.

◆ BS_DrvNum

#define BS_DrvNum   36 /* Physical drive number (1) */

Definition at line 383 of file ff.c.

◆ BS_DrvNum32

#define BS_DrvNum32   64 /* Physical drive number (1) */

Definition at line 395 of file ff.c.

◆ BS_FilSysType

#define BS_FilSysType   54 /* File system type (1) */

Definition at line 388 of file ff.c.

◆ BS_FilSysType32

#define BS_FilSysType32   82 /* File system type (1) */

Definition at line 400 of file ff.c.

◆ BS_jmpBoot

#define BS_jmpBoot   0 /* x86 jump instruction (3) */

Definition at line 369 of file ff.c.

◆ BS_NTres

#define BS_NTres   37 /* Error flag (1) */

Definition at line 384 of file ff.c.

◆ BS_NTres32

#define BS_NTres32   65 /* Error flag (1) */

Definition at line 396 of file ff.c.

◆ BS_OEMName

#define BS_OEMName   3 /* OEM name (8) */

Definition at line 370 of file ff.c.

◆ BS_VolID

#define BS_VolID   39 /* Volume serial number (4) */

Definition at line 386 of file ff.c.

◆ BS_VolID32

#define BS_VolID32   67 /* Volume serial number (4) */

Definition at line 398 of file ff.c.

◆ BS_VolLab

#define BS_VolLab   43 /* Volume label (8) */

Definition at line 387 of file ff.c.

◆ BS_VolLab32

#define BS_VolLab32   71 /* Volume label (8) */

Definition at line 399 of file ff.c.

◆ DDEM

#define DDEM   0xE5 /* Deleted directory entry mark at DIR_Name[0] */

Definition at line 428 of file ff.c.

◆ DEFINE_NAMEBUF

#define DEFINE_NAMEBUF   BYTE sfn[12]; WCHAR lbuf[_MAX_LFN + 1]

Definition at line 473 of file ff.c.

◆ DIR_Attr

#define DIR_Attr   11 /* Attribute (1) */

Definition at line 410 of file ff.c.

◆ DIR_CrtDate

#define DIR_CrtDate   16 /* Created date (2) */

Definition at line 414 of file ff.c.

◆ DIR_CrtTime

#define DIR_CrtTime   14 /* Created time (2) */

Definition at line 413 of file ff.c.

◆ DIR_CrtTimeTenth

#define DIR_CrtTimeTenth   13 /* Created time sub-second (1) */

Definition at line 412 of file ff.c.

◆ DIR_FileSize

#define DIR_FileSize   28 /* File size (4) */

Definition at line 420 of file ff.c.

◆ DIR_FstClusHI

#define DIR_FstClusHI   20 /* Higher 16-bit of first cluster (2) */

Definition at line 416 of file ff.c.

◆ DIR_FstClusLO

#define DIR_FstClusLO   26 /* Lower 16-bit of first cluster (2) */

Definition at line 419 of file ff.c.

◆ DIR_LstAccDate

#define DIR_LstAccDate   18 /* Last accessed date (2) */

Definition at line 415 of file ff.c.

◆ DIR_Name

#define DIR_Name   0 /* Short file name (11) */

Definition at line 409 of file ff.c.

◆ DIR_NTres

#define DIR_NTres   12 /* Lower case flag (1) */

Definition at line 411 of file ff.c.

◆ DIR_WrtDate

#define DIR_WrtDate   24 /* Modified date (2) */

Definition at line 418 of file ff.c.

◆ DIR_WrtTime

#define DIR_WrtTime   22 /* Modified time (2) */

Definition at line 417 of file ff.c.

◆ ENTER_FF

#define ENTER_FF (   fs)

Definition at line 42 of file ff.c.

◆ FREE_BUF

#define FREE_BUF ( )

Definition at line 475 of file ff.c.

◆ FSI_Free_Count

#define FSI_Free_Count   488 /* FSI: Number of free clusters (4) */

Definition at line 403 of file ff.c.

◆ FSI_LeadSig

#define FSI_LeadSig   0 /* FSI: Leading signature (4) */

Definition at line 401 of file ff.c.

◆ FSI_Nxt_Free

#define FSI_Nxt_Free   492 /* FSI: Last allocated cluster (4) */

Definition at line 404 of file ff.c.

◆ FSI_StrucSig

#define FSI_StrucSig   484 /* FSI: Structure signature (4) */

Definition at line 402 of file ff.c.

◆ GET_FATTIME

#define GET_FATTIME ( )    get_fattime()

Definition at line 67 of file ff.c.

◆ INIT_BUF

#define INIT_BUF (   dobj)    { (dobj).fn = sfn; (dobj).lfn = lbuf; }

Definition at line 474 of file ff.c.

◆ IsDBCS1

#define IsDBCS1 (   c)    0

Definition at line 344 of file ff.c.

◆ IsDBCS2

#define IsDBCS2 (   c)    0

Definition at line 345 of file ff.c.

◆ IsDigit

#define IsDigit (   c)    (((c)>='0')&&((c)<='9'))

Definition at line 326 of file ff.c.

◆ IsLower

#define IsLower (   c)    (((c)>='a')&&((c)<='z'))

Definition at line 325 of file ff.c.

◆ IsUpper

#define IsUpper (   c)    (((c)>='A')&&((c)<='Z'))

Definition at line 324 of file ff.c.

◆ LDIR_Attr

#define LDIR_Attr   11 /* LFN attribute (1) */

Definition at line 422 of file ff.c.

◆ LDIR_Chksum

#define LDIR_Chksum   13 /* Checksum of corresponding SFN entry */

Definition at line 424 of file ff.c.

◆ LDIR_FstClusLO

#define LDIR_FstClusLO   26 /* Must be zero (0) */

Definition at line 425 of file ff.c.

◆ LDIR_Ord

#define LDIR_Ord   0 /* LFN entry order and LLE flag (1) */

Definition at line 421 of file ff.c.

◆ LDIR_Type

#define LDIR_Type   12 /* LFN type (1) */

Definition at line 423 of file ff.c.

◆ LEAVE_FF

#define LEAVE_FF (   fs,
  res 
)    return res

Definition at line 43 of file ff.c.

◆ LLEF

#define LLEF   0x40 /* Last long entry flag in LDIR_Ord */

Definition at line 427 of file ff.c.

◆ MBR_Table

#define MBR_Table   446 /* MBR: Partition table offset (2) */

Definition at line 405 of file ff.c.

◆ MIN_FAT16

#define MIN_FAT16   4086U /* Minimum number of clusters of FAT16 */

Definition at line 361 of file ff.c.

◆ MIN_FAT32

#define MIN_FAT32   65526U /* Minimum number of clusters of FAT32 */

Definition at line 362 of file ff.c.

◆ N_FATS

#define N_FATS   2 /* Number of FATs (1 or 2) */

Definition at line 4065 of file ff.c.

◆ N_ROOTDIR12

#define N_ROOTDIR12   224 /* Number of root directory entries for FAT12 */

Definition at line 4063 of file ff.c.

◆ N_ROOTDIR16

#define N_ROOTDIR16   512 /* Number of root directory entries for FAT16 */

Definition at line 4064 of file ff.c.

◆ NS_BODY

#define NS_BODY   0x08 /* Lower case flag (body) */

Definition at line 355 of file ff.c.

◆ NS_DOT

#define NS_DOT   0x20 /* Dot entry */

Definition at line 357 of file ff.c.

◆ NS_EXT

#define NS_EXT   0x10 /* Lower case flag (ext) */

Definition at line 356 of file ff.c.

◆ NS_LAST

#define NS_LAST   0x04 /* Last segment */

Definition at line 354 of file ff.c.

◆ NS_LFN

#define NS_LFN   0x02 /* Force to create LFN entry */

Definition at line 353 of file ff.c.

◆ NS_LOSS

#define NS_LOSS   0x01 /* Out of 8.3 format */

Definition at line 352 of file ff.c.

◆ NSFLAG

#define NSFLAG   11 /* Index of name status byte in fn[] */

Definition at line 351 of file ff.c.

◆ RDDEM

#define RDDEM   0x05 /* Replacement of the character collides with DDEM */

Definition at line 429 of file ff.c.

◆ SS

#define SS (   fs)    ((UINT)_MAX_SS) /* Fixed sector size */

Definition at line 54 of file ff.c.

◆ SZ_DIRE

#define SZ_DIRE   32 /* Size of a directory entry */

Definition at line 426 of file ff.c.

◆ SZ_PTE

#define SZ_PTE   16 /* MBR: Size of a partition table entry */

Definition at line 406 of file ff.c.

Function Documentation

◆ check_fs()

static BYTE check_fs ( FATFS fs,
DWORD  sect 
)
static

Definition at line 2175 of file ff.c.

2179{
2180 fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */
2181 if (move_window(fs, sect) != FR_OK) /* Load boot record */
2182 return 3;
2183
2184 if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check boot record signature (always placed at offset 510 even if the sector size is >512) */
2185 return 2;
2186
2187 if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */
2188 return 0;
2189 if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */
2190 return 0;
2191
2192 return 1;
2193}
#define BS_FilSysType
Definition: ff.c:388
#define BS_55AA
Definition: ff.c:407
#define BS_FilSysType32
Definition: ff.c:400
static FRESULT move_window(FATFS *fs, DWORD sector)
Definition: ff.c:729
#define LD_WORD(ptr)
Definition: ff.h:340
#define LD_DWORD(ptr)
Definition: ff.h:341
@ FR_OK
Definition: ff.h:185
Definition: ffs.h:70

Referenced by find_volume().

◆ chk_chr()

static int chk_chr ( const char str,
int  chr 
)
static

Definition at line 543 of file ff.c.

543 {
544 while (*str && *str != chr) str++;
545 return *str;
546}
const WCHAR * str

Referenced by create_name(), and f_setlabel().

◆ clust2sect()

DWORD clust2sect ( FATFS fs,
DWORD  clst 
)

Definition at line 800 of file ff.c.

804{
805 clst -= 2;
806 if (clst >= fs->n_fatent - 2) return 0; /* Invalid cluster# */
807 return clst * fs->csize + fs->database;
808}

Referenced by dir_next(), dir_sdi(), f_lseek(), f_mkdir(), f_read(), f_rename(), f_write(), and remove_chain().

◆ cmp_lfn()

static int cmp_lfn ( WCHAR lfnbuf,
BYTE dir 
)
static

Definition at line 1274 of file ff.c.

1278{
1279 UINT i, s;
1280 WCHAR wc, uc;
1281
1282
1283 if (LD_WORD(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */
1284
1285 i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
1286
1287 for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
1288 uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character */
1289 if (wc) {
1290 if (i >= _MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) /* Compare it */
1291 return 0; /* Not matched */
1292 wc = uc;
1293 } else {
1294 if (uc != 0xFFFF) return 0; /* Check filler */
1295 }
1296 }
1297
1298 if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) /* Last segment matched but different length */
1299 return 0;
1300
1301 return 1; /* The part of LFN matched */
1302}
unsigned int dir
Definition: maze.c:112
#define LLEF
Definition: ff.c:427
static const BYTE LfnOfs[]
Definition: ff.c:1270
#define LDIR_Ord
Definition: ff.c:421
#define LDIR_FstClusLO
Definition: ff.c:425
WCHAR ff_wtoupper(WCHAR chr)
Definition: ccsbcs.c:304
#define _MAX_LFN
Definition: ffconf.h:94
GLdouble s
Definition: gl.h:2039
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned int UINT
Definition: ndis.h:50
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by dir_find().

◆ create_chain()

static DWORD create_chain ( FATFS fs,
DWORD  clst 
)
static

Definition at line 990 of file ff.c.

994{
995 DWORD cs, ncl, scl;
996 FRESULT res;
997
998
999 if (clst == 0) { /* Create a new chain */
1000 scl = fs->last_clust; /* Get suggested start point */
1001 if (!scl || scl >= fs->n_fatent) scl = 1;
1002 }
1003 else { /* Stretch the current chain */
1004 cs = get_fat(fs, clst); /* Check the cluster status */
1005 if (cs < 2) return 1; /* Invalid value */
1006 if (cs == 0xFFFFFFFF) return cs; /* A disk error occurred */
1007 if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */
1008 scl = clst;
1009 }
1010
1011 ncl = scl; /* Start cluster */
1012 for (;;) {
1013 ncl++; /* Next cluster */
1014 if (ncl >= fs->n_fatent) { /* Check wrap around */
1015 ncl = 2;
1016 if (ncl > scl) return 0; /* No free cluster */
1017 }
1018 cs = get_fat(fs, ncl); /* Get the cluster status */
1019 if (cs == 0) break; /* Found a free cluster */
1020 if (cs == 0xFFFFFFFF || cs == 1)/* An error occurred */
1021 return cs;
1022 if (ncl == scl) return 0; /* No free cluster */
1023 }
1024
1025 res = put_fat(fs, ncl, 0x0FFFFFFF); /* Mark the new cluster "last link" */
1026 if (res == FR_OK && clst != 0) {
1027 res = put_fat(fs, clst, ncl); /* Link it to the previous one if needed */
1028 }
1029 if (res == FR_OK) {
1030 fs->last_clust = ncl; /* Update FSINFO */
1031 if (fs->free_clust != 0xFFFFFFFF) {
1032 fs->free_clust--;
1033 fs->fsi_flag |= 1;
1034 }
1035 } else {
1036 ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;
1037 }
1038
1039 return ncl; /* Return new cluster number or error code */
1040}
DWORD get_fat(FATFS *fs, DWORD clst)
Definition: ff.c:818
FRESULT put_fat(FATFS *fs, DWORD clst, DWORD val)
Definition: ff.c:873
FRESULT
Definition: ff.h:184
@ FR_DISK_ERR
Definition: ff.h:186
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint res
Definition: glext.h:9613
#define cs
Definition: i386-dis.c:442

◆ create_name()

static FRESULT create_name ( DIR dp,
const TCHAR **  path 
)
static

Definition at line 1843 of file ff.c.

1847{
1848#if _USE_LFN /* LFN configuration */
1849 BYTE b, cf;
1850 WCHAR w, *lfn;
1851 UINT i, ni, si, di;
1852 const TCHAR *p;
1853
1854 /* Create LFN in Unicode */
1855 for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Strip duplicated separator */
1856 lfn = dp->lfn;
1857 si = di = 0;
1858 for (;;) {
1859 w = p[si++]; /* Get a character */
1860 if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */
1861 if (di >= _MAX_LFN) /* Reject too long name */
1862 return FR_INVALID_NAME;
1863#if !_LFN_UNICODE
1864 w &= 0xFF;
1865 if (IsDBCS1(w)) { /* Check if it is a DBC 1st byte (always false on SBCS cfg) */
1866 b = (BYTE)p[si++]; /* Get 2nd byte */
1867 w = (w << 8) + b; /* Create a DBC */
1868 if (!IsDBCS2(b))
1869 return FR_INVALID_NAME; /* Reject invalid sequence */
1870 }
1871 w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */
1872 if (!w) return FR_INVALID_NAME; /* Reject invalid code */
1873#endif
1874 if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject illegal characters for LFN */
1875 return FR_INVALID_NAME;
1876 lfn[di++] = w; /* Store the Unicode character */
1877 }
1878 *path = &p[si]; /* Return pointer to the next segment */
1879 cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
1880#if _FS_RPATH
1881 if ((di == 1 && lfn[di - 1] == '.') ||
1882 (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot entry? */
1883 lfn[di] = 0;
1884 for (i = 0; i < 11; i++) /* Create dot name for SFN entry */
1885 dp->fn[i] = (i < di) ? '.' : ' ';
1886 dp->fn[i] = cf | NS_DOT; /* This is a dot entry */
1887 return FR_OK;
1888 }
1889#endif
1890 while (di) { /* Snip off trailing spaces and dots if exist */
1891 w = lfn[di - 1];
1892 if (w != ' ' && w != '.') break;
1893 di--;
1894 }
1895 if (!di) return FR_INVALID_NAME; /* Reject nul string */
1896 lfn[di] = 0; /* LFN is created */
1897
1898 /* Create SFN in directory form */
1899 mem_set(dp->fn, ' ', 11);
1900 for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */
1901 if (si) cf |= NS_LOSS | NS_LFN;
1902 while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */
1903
1904 b = i = 0; ni = 8;
1905 for (;;) {
1906 w = lfn[si++]; /* Get an LFN character */
1907 if (!w) break; /* Break on end of the LFN */
1908 if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */
1909 cf |= NS_LOSS | NS_LFN; continue;
1910 }
1911
1912 if (i >= ni || si == di) { /* Extension or end of SFN */
1913 if (ni == 11) { /* Long extension */
1914 cf |= NS_LOSS | NS_LFN; break;
1915 }
1916 if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */
1917 if (si > di) break; /* No extension */
1918 si = di; i = 8; ni = 11; /* Enter extension section */
1919 b <<= 2; continue;
1920 }
1921
1922 if (w >= 0x80) { /* Non ASCII character */
1923#ifdef _EXCVT
1924 w = ff_convert(w, 0); /* Unicode -> OEM code */
1925 if (w) w = ExCvt[w - 0x80]; /* Convert extended character to upper (SBCS) */
1926#else
1927 w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */
1928#endif
1929 cf |= NS_LFN; /* Force create LFN entry */
1930 }
1931
1932 if (_DF1S && w >= 0x100) { /* Is this DBC? (always false at SBCS cfg) */
1933 if (i >= ni - 1) {
1934 cf |= NS_LOSS | NS_LFN; i = ni; continue;
1935 }
1936 dp->fn[i++] = (BYTE)(w >> 8);
1937 } else { /* SBC */
1938 if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal characters for SFN */
1939 w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
1940 } else {
1941 if (IsUpper(w)) { /* ASCII large capital */
1942 b |= 2;
1943 } else {
1944 if (IsLower(w)) { /* ASCII small capital */
1945 b |= 1; w -= 0x20;
1946 }
1947 }
1948 }
1949 }
1950 dp->fn[i++] = (BYTE)w;
1951 }
1952
1953 if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */
1954
1955 if (ni == 8) b <<= 2;
1956 if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */
1957 cf |= NS_LFN;
1958 if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */
1959 if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */
1960 if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */
1961 }
1962
1963 dp->fn[NSFLAG] = cf; /* SFN is created */
1964
1965 return FR_OK;
1966
1967
1968#else /* Non-LFN configuration */
1969 BYTE b, c, d, *sfn;
1970 UINT ni, si, i;
1971 const char *p;
1972
1973 /* Create file name in directory form */
1974 for (p = *path; *p == '/' || *p == '\\'; p++) ; /* Skip duplicated separator */
1975 sfn = dp->fn;
1976 mem_set(sfn, ' ', 11);
1977 si = i = b = 0; ni = 8;
1978#if _FS_RPATH
1979 if (p[si] == '.') { /* Is this a dot entry? */
1980 for (;;) {
1981 c = (BYTE)p[si++];
1982 if (c != '.' || si >= 3) break;
1983 sfn[i++] = c;
1984 }
1985 if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
1986 *path = &p[si]; /* Return pointer to the next segment */
1987 sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of path */
1988 return FR_OK;
1989 }
1990#endif
1991 for (;;) {
1992 c = (BYTE)p[si++];
1993 if (c <= ' ' || c == '/' || c == '\\') break; /* Break on end of segment */
1994 if (c == '.' || i >= ni) {
1995 if (ni != 8 || c != '.') return FR_INVALID_NAME;
1996 i = 8; ni = 11;
1997 b <<= 2; continue;
1998 }
1999 if (c >= 0x80) { /* Extended character? */
2000 b |= 3; /* Eliminate NT flag */
2001#ifdef _EXCVT
2002 c = ExCvt[c - 0x80]; /* To upper extended characters (SBCS cfg) */
2003#else
2004#if !_DF1S
2005 return FR_INVALID_NAME; /* Reject extended characters (ASCII cfg) */
2006#endif
2007#endif
2008 }
2009 if (IsDBCS1(c)) { /* Check if it is a DBC 1st byte (always false at SBCS cfg.) */
2010 d = (BYTE)p[si++]; /* Get 2nd byte */
2011 if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */
2012 return FR_INVALID_NAME;
2013 sfn[i++] = c;
2014 sfn[i++] = d;
2015 } else { /* SBC */
2016 if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) /* Reject illegal chrs for SFN */
2017 return FR_INVALID_NAME;
2018 if (IsUpper(c)) { /* ASCII large capital? */
2019 b |= 2;
2020 } else {
2021 if (IsLower(c)) { /* ASCII small capital? */
2022 b |= 1; c -= 0x20;
2023 }
2024 }
2025 sfn[i++] = c;
2026 }
2027 }
2028 *path = &p[si]; /* Return pointer to the next segment */
2029 c = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */
2030
2031 if (!i) return FR_INVALID_NAME; /* Reject nul string */
2032 if (sfn[0] == DDEM) sfn[0] = RDDEM; /* When first character collides with DDEM, replace it with RDDEM */
2033
2034 if (ni == 8) b <<= 2;
2035 if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Name extension has only small capital) */
2036 if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Name body has only small capital) */
2037
2038 sfn[NSFLAG] = c; /* Store NT flag, File name is created */
2039
2040 return FR_OK;
2041#endif
2042}
OPENFILENAMEW sfn
Definition: eventvwr.c:101
static void mem_set(void *dst, int val, UINT cnt)
Definition: ff.c:524
#define DDEM
Definition: ff.c:428
static int chk_chr(const char *str, int chr)
Definition: ff.c:543
#define _DF1S
Definition: ff.c:125
#define RDDEM
Definition: ff.c:429
#define NS_DOT
Definition: ff.c:357
#define NS_EXT
Definition: ff.c:356
#define NS_BODY
Definition: ff.c:355
#define IsLower(c)
Definition: ff.c:325
#define IsDBCS1(c)
Definition: ff.c:344
#define NS_LAST
Definition: ff.c:354
#define IsDBCS2(c)
Definition: ff.c:345
#define IsUpper(c)
Definition: ff.c:324
#define NS_LOSS
Definition: ff.c:352
#define NSFLAG
Definition: ff.c:351
static const BYTE ExCvt[]
Definition: ff.c:486
#define NS_LFN
Definition: ff.c:353
@ FR_INVALID_NAME
Definition: ff.h:191
WCHAR ff_convert(WCHAR chr, UINT dir)
Definition: ccsbcs.c:275
static struct netconfig_info ni
Definition: getnetconfig.c:158
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
#define d
Definition: ke_i.h:81
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
BYTE * fn
Definition: ff.h:151
WCHAR * lfn
Definition: ff.h:156
char TCHAR
Definition: xmlstorage.h:189
unsigned char BYTE
Definition: xxhash.c:193

Referenced by follow_path().

◆ dir_alloc()

static FRESULT dir_alloc ( DIR dp,
UINT  nent 
)
static

Definition at line 1199 of file ff.c.

1203{
1204 FRESULT res;
1205 UINT n;
1206
1207
1208 res = dir_sdi(dp, 0);
1209 if (res == FR_OK) {
1210 n = 0;
1211 do {
1212 res = move_window(dp->fs, dp->sect);
1213 if (res != FR_OK) break;
1214 if (dp->dir[0] == DDEM || dp->dir[0] == 0) { /* Is it a free entry? */
1215 if (++n == nent) break; /* A block of contiguous free entries is found */
1216 } else {
1217 n = 0; /* Not a blank entry. Restart to search */
1218 }
1219 res = dir_next(dp, 1); /* Next entry with table stretch enabled */
1220 } while (res == FR_OK);
1221 }
1222 if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */
1223 return res;
1224}
static FRESULT dir_sdi(DIR *dp, UINT idx)
Definition: ff.c:1080
static FRESULT dir_next(DIR *dp, int stretch)
Definition: ff.c:1128
@ FR_DENIED
Definition: ff.h:192
@ FR_NO_FILE
Definition: ff.h:189
GLdouble n
Definition: glext.h:7729
FATFS * fs
Definition: ff.h:144
BYTE * dir
Definition: ff.h:150
DWORD sect
Definition: ff.h:149

Referenced by dir_register(), and f_setlabel().

◆ dir_find()

static FRESULT dir_find ( DIR dp)
static

Definition at line 1458 of file ff.c.

1461{
1462 FRESULT res;
1463 BYTE c, *dir;
1464#if _USE_LFN
1465 BYTE a, ord, sum;
1466#endif
1467
1468 res = dir_sdi(dp, 0); /* Rewind directory object */
1469 if (res != FR_OK) return res;
1470
1471#if _USE_LFN
1472 ord = sum = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
1473#endif
1474 do {
1475 res = move_window(dp->fs, dp->sect);
1476 if (res != FR_OK) break;
1477 dir = dp->dir; /* Ptr to the directory entry of current index */
1478 c = dir[DIR_Name];
1479 if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
1480#if _USE_LFN /* LFN configuration */
1481 a = dir[DIR_Attr] & AM_MASK;
1482 if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */
1483 ord = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
1484 } else {
1485 if (a == AM_LFN) { /* An LFN entry is found */
1486 if (dp->lfn) {
1487 if (c & LLEF) { /* Is it start of LFN sequence? */
1488 sum = dir[LDIR_Chksum];
1489 c &= ~LLEF; ord = c; /* LFN start order */
1490 dp->lfn_idx = dp->index; /* Start index of LFN */
1491 }
1492 /* Check validity of the LFN entry and compare it with given name */
1493 ord = (c == ord && sum == dir[LDIR_Chksum] && cmp_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF;
1494 }
1495 } else { /* An SFN entry is found */
1496 if (!ord && sum == sum_sfn(dir)) break; /* LFN matched? */
1497 if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dir, dp->fn, 11)) break; /* SFN matched? */
1498 ord = 0xFF; dp->lfn_idx = 0xFFFF; /* Reset LFN sequence */
1499 }
1500 }
1501#else /* Non LFN configuration */
1502 if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dp->fn, 11)) /* Is it a valid entry? */
1503 break;
1504#endif
1505 res = dir_next(dp, 0); /* Next entry */
1506 } while (res == FR_OK);
1507
1508 return res;
1509}
static int mem_cmp(const void *dst, const void *src, UINT cnt)
Definition: ff.c:533
static BYTE sum_sfn(const BYTE *dir)
Definition: ff.c:1438
static int cmp_lfn(WCHAR *lfnbuf, BYTE *dir)
Definition: ff.c:1274
#define DIR_Attr
Definition: ff.c:410
#define LDIR_Chksum
Definition: ff.c:424
#define DIR_Name
Definition: ff.c:409
#define AM_VOL
Definition: ff.h:319
#define AM_LFN
Definition: ff.h:320
#define AM_MASK
Definition: ff.h:323
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
#define a
Definition: ke_i.h:78
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
WORD index
Definition: ff.h:146
WORD lfn_idx
Definition: ff.h:157

Referenced by dir_register(), and follow_path().

◆ dir_next()

static FRESULT dir_next ( DIR dp,
int  stretch 
)
static

Definition at line 1128 of file ff.c.

1132{
1133 DWORD clst;
1134 UINT i;
1135#if !_FS_READONLY
1136 UINT c;
1137#endif
1138
1139
1140 i = dp->index + 1;
1141 if (!(i & 0xFFFF) || !dp->sect) /* Report EOT when index has reached 65535 */
1142 return FR_NO_FILE;
1143
1144 if (!(i % (SS(dp->fs) / SZ_DIRE))) { /* Sector changed? */
1145 dp->sect++; /* Next sector */
1146
1147 if (!dp->clust) { /* Static table */
1148 if (i >= dp->fs->n_rootdir) /* Report EOT if it reached end of static table */
1149 return FR_NO_FILE;
1150 }
1151 else { /* Dynamic table */
1152 if (((i / (SS(dp->fs) / SZ_DIRE)) & (dp->fs->csize - 1)) == 0) { /* Cluster changed? */
1153 clst = get_fat(dp->fs, dp->clust); /* Get next cluster */
1154 if (clst <= 1) return FR_INT_ERR;
1155 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
1156 if (clst >= dp->fs->n_fatent) { /* If it reached end of dynamic table, */
1157#if !_FS_READONLY
1158 if (!stretch) return FR_NO_FILE; /* If do not stretch, report EOT */
1159 clst = create_chain(dp->fs, dp->clust); /* Stretch cluster chain */
1160 if (clst == 0) return FR_DENIED; /* No free cluster */
1161 if (clst == 1) return FR_INT_ERR;
1162 if (clst == 0xFFFFFFFF) return FR_DISK_ERR;
1163 /* Clean-up stretched table */
1164 if (sync_window(dp->fs)) return FR_DISK_ERR;/* Flush disk access window */
1165 mem_set(dp->fs->win, 0, SS(dp->fs)); /* Clear window buffer */
1166 dp->fs->winsect = clust2sect(dp->fs, clst); /* Cluster start sector */
1167 for (c = 0; c < dp->fs->csize; c++) { /* Fill the new cluster with 0 */
1168 dp->fs->wflag = 1;
1169 if (sync_window(dp->fs)) return FR_DISK_ERR;
1170 dp->fs->winsect++;
1171 }
1172 dp->fs->winsect -= c; /* Rewind window offset */
1173#else
1174 if (!stretch) return FR_NO_FILE; /* If do not stretch, report EOT (this is to suppress warning) */
1175 return FR_NO_FILE; /* Report EOT */
1176#endif
1177 }
1178 dp->clust = clst; /* Initialize data for new cluster */
1179 dp->sect = clust2sect(dp->fs, clst);
1180 }
1181 }
1182 }
1183
1184 dp->index = (WORD)i; /* Current index */
1185 dp->dir = dp->fs->win + (i % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; /* Current entry in the window */
1186
1187 return FR_OK;
1188}
static MSG_ENTRY create_chain[]
#define SS(fs)
Definition: ff.c:54
#define SZ_DIRE
Definition: ff.c:426
static FRESULT sync_window(FATFS *fs)
Definition: ff.c:700
DWORD clust2sect(FATFS *fs, DWORD clst)
Definition: ff.c:800
@ FR_INT_ERR
Definition: ff.h:187
unsigned short WORD
Definition: ntddk_ex.h:93
DWORD clust
Definition: ff.h:148
WORD n_rootdir
Definition: ff.h:86
BYTE csize
Definition: ff.h:81
BYTE wflag
Definition: ff.h:83
BYTE win[_MAX_SS]
Definition: ff.h:107
DWORD n_fatent
Definition: ff.h:100
DWORD winsect
Definition: ff.h:106

Referenced by dir_alloc(), dir_find(), dir_read(), dir_register(), dir_remove(), and f_readdir().

◆ dir_read()

static FRESULT dir_read ( DIR dp,
int  vol 
)
static

Definition at line 1519 of file ff.c.

1523{
1524 FRESULT res;
1525 BYTE a, c, *dir;
1526#if _USE_LFN
1527 BYTE ord = 0xFF, sum = 0xFF;
1528#endif
1529
1530 res = FR_NO_FILE;
1531 while (dp->sect) {
1532 res = move_window(dp->fs, dp->sect);
1533 if (res != FR_OK) break;
1534 dir = dp->dir; /* Ptr to the directory entry of current index */
1535 c = dir[DIR_Name];
1536 if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */
1537 a = dir[DIR_Attr] & AM_MASK;
1538#if _USE_LFN /* LFN configuration */
1539 if (c == DDEM || (!_FS_RPATH && c == '.') || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
1540 ord = 0xFF;
1541 } else {
1542 if (a == AM_LFN) { /* An LFN entry is found */
1543 if (c & LLEF) { /* Is it start of LFN sequence? */
1544 sum = dir[LDIR_Chksum];
1545 c &= ~LLEF; ord = c;
1546 dp->lfn_idx = dp->index;
1547 }
1548 /* Check LFN validity and capture it */
1549 ord = (c == ord && sum == dir[LDIR_Chksum] && pick_lfn(dp->lfn, dir)) ? ord - 1 : 0xFF;
1550 } else { /* An SFN entry is found */
1551 if (ord || sum != sum_sfn(dir)) /* Is there a valid LFN? */
1552 dp->lfn_idx = 0xFFFF; /* It has no LFN. */
1553 break;
1554 }
1555 }
1556#else /* Non LFN configuration */
1557 if (c != DDEM && (_FS_RPATH || c != '.') && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) /* Is it a valid entry? */
1558 break;
1559#endif
1560 res = dir_next(dp, 0); /* Next entry */
1561 if (res != FR_OK) break;
1562 }
1563
1564 if (res != FR_OK) dp->sect = 0;
1565
1566 return res;
1567}
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static int pick_lfn(WCHAR *lfnbuf, BYTE *dir)
Definition: ff.c:1307
#define AM_ARC
Definition: ff.h:322
#define _FS_RPATH
Definition: ffconf.h:127

Referenced by f_getlabel(), f_readdir(), f_setlabel(), and f_unlink().

◆ dir_register()

static FRESULT dir_register ( DIR dp)
static

Definition at line 1578 of file ff.c.

1581{
1582 FRESULT res;
1583#if _USE_LFN /* LFN configuration */
1584 UINT n, nent;
1585 BYTE sn[12], *fn, sum;
1586 WCHAR *lfn;
1587
1588
1589 fn = dp->fn; lfn = dp->lfn;
1590 mem_cpy(sn, fn, 12);
1591
1592 if (_FS_RPATH && (sn[NSFLAG] & NS_DOT)) /* Cannot create dot entry */
1593 return FR_INVALID_NAME;
1594
1595 if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */
1596 fn[NSFLAG] = 0; dp->lfn = 0; /* Find only SFN */
1597 for (n = 1; n < 100; n++) {
1598 gen_numname(fn, sn, lfn, n); /* Generate a numbered name */
1599 res = dir_find(dp); /* Check if the name collides with existing SFN */
1600 if (res != FR_OK) break;
1601 }
1602 if (n == 100) return FR_DENIED; /* Abort if too many collisions */
1603 if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */
1604 fn[NSFLAG] = sn[NSFLAG]; dp->lfn = lfn;
1605 }
1606
1607 if (sn[NSFLAG] & NS_LFN) { /* When LFN is to be created, allocate entries for an SFN + LFNs. */
1608 for (n = 0; lfn[n]; n++) ;
1609 nent = (n + 25) / 13;
1610 } else { /* Otherwise allocate an entry for an SFN */
1611 nent = 1;
1612 }
1613 res = dir_alloc(dp, nent); /* Allocate entries */
1614
1615 if (res == FR_OK && --nent) { /* Set LFN entry if needed */
1616 res = dir_sdi(dp, dp->index - nent);
1617 if (res == FR_OK) {
1618 sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */
1619 do { /* Store LFN entries in bottom first */
1620 res = move_window(dp->fs, dp->sect);
1621 if (res != FR_OK) break;
1622 fit_lfn(dp->lfn, dp->dir, (BYTE)nent, sum);
1623 dp->fs->wflag = 1;
1624 res = dir_next(dp, 0); /* Next entry */
1625 } while (res == FR_OK && --nent);
1626 }
1627 }
1628#else /* Non LFN configuration */
1629 res = dir_alloc(dp, 1); /* Allocate an entry for SFN */
1630#endif
1631
1632 if (res == FR_OK) { /* Set SFN entry */
1633 res = move_window(dp->fs, dp->sect);
1634 if (res == FR_OK) {
1635 mem_set(dp->dir, 0, SZ_DIRE); /* Clean the entry */
1636 mem_cpy(dp->dir, dp->fn, 11); /* Put SFN */
1637#if _USE_LFN
1638 dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */
1639#endif
1640 dp->fs->wflag = 1;
1641 }
1642 }
1643
1644 return res;
1645}
static void gen_numname(BYTE *dst, const BYTE *src, const WCHAR *lfn, UINT seq)
Definition: ff.c:1379
static FRESULT dir_alloc(DIR *dp, UINT nent)
Definition: ff.c:1199
static void fit_lfn(const WCHAR *lfnbuf, BYTE *dir, BYTE ord, BYTE sum)
Definition: ff.c:1341
#define DIR_NTres
Definition: ff.c:411
static void mem_cpy(void *dst, const void *src, UINT cnt)
Definition: ff.c:507
static FRESULT dir_find(DIR *dp)
Definition: ff.c:1458
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159

Referenced by f_mkdir(), f_open(), and f_rename().

◆ dir_remove()

static FRESULT dir_remove ( DIR dp)
static

Definition at line 1656 of file ff.c.

1659{
1660 FRESULT res;
1661#if _USE_LFN /* LFN configuration */
1662 UINT i;
1663
1664 i = dp->index; /* SFN index */
1665 res = dir_sdi(dp, (dp->lfn_idx == 0xFFFF) ? i : dp->lfn_idx); /* Goto the SFN or top of the LFN entries */
1666 if (res == FR_OK) {
1667 do {
1668 res = move_window(dp->fs, dp->sect);
1669 if (res != FR_OK) break;
1670 mem_set(dp->dir, 0, SZ_DIRE); /* Clear and mark the entry "deleted" */
1671 *dp->dir = DDEM;
1672 dp->fs->wflag = 1;
1673 if (dp->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */
1674 res = dir_next(dp, 0); /* Next entry */
1675 } while (res == FR_OK);
1676 if (res == FR_NO_FILE) res = FR_INT_ERR;
1677 }
1678
1679#else /* Non LFN configuration */
1680 res = dir_sdi(dp, dp->index);
1681 if (res == FR_OK) {
1682 res = move_window(dp->fs, dp->sect);
1683 if (res == FR_OK) {
1684 mem_set(dp->dir, 0, SZ_DIRE); /* Clear and mark the entry "deleted" */
1685 *dp->dir = DDEM;
1686 dp->fs->wflag = 1;
1687 }
1688 }
1689#endif
1690
1691 return res;
1692}

Referenced by f_rename(), and f_unlink().

◆ dir_sdi()

static FRESULT dir_sdi ( DIR dp,
UINT  idx 
)
static

Definition at line 1080 of file ff.c.

1084{
1085 DWORD clst, sect;
1086 UINT ic;
1087
1088
1089 dp->index = (WORD)idx; /* Current index */
1090 clst = dp->sclust; /* Table start cluster (0:root) */
1091 if (clst == 1 || clst >= dp->fs->n_fatent) /* Check start cluster range */
1092 return FR_INT_ERR;
1093 if (!clst && dp->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */
1094 clst = dp->fs->dirbase;
1095
1096 if (clst == 0) { /* Static table (root-directory in FAT12/16) */
1097 if (idx >= dp->fs->n_rootdir) /* Is index out of range? */
1098 return FR_INT_ERR;
1099 sect = dp->fs->dirbase;
1100 }
1101 else { /* Dynamic table (root-directory in FAT32 or sub-directory) */
1102 ic = SS(dp->fs) / SZ_DIRE * dp->fs->csize; /* Entries per cluster */
1103 while (idx >= ic) { /* Follow cluster chain */
1104 clst = get_fat(dp->fs, clst); /* Get next cluster */
1105 if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */
1106 if (clst < 2 || clst >= dp->fs->n_fatent) /* Reached to end of table or internal error */
1107 return FR_INT_ERR;
1108 idx -= ic;
1109 }
1110 sect = clust2sect(dp->fs, clst);
1111 }
1112 dp->clust = clst; /* Current cluster# */
1113 if (!sect) return FR_INT_ERR;
1114 dp->sect = sect + idx / (SS(dp->fs) / SZ_DIRE); /* Sector# of the directory entry */
1115 dp->dir = dp->fs->win + (idx % (SS(dp->fs) / SZ_DIRE)) * SZ_DIRE; /* Ptr to the entry in the sector */
1116
1117 return FR_OK;
1118}
unsigned int idx
Definition: utils.c:41
#define FS_FAT32
Definition: ff.h:311
DWORD sclust
Definition: ff.h:147
DWORD dirbase
Definition: ff.h:104
BYTE fs_type
Definition: ff.h:79

Referenced by dir_alloc(), dir_find(), dir_register(), dir_remove(), f_getlabel(), f_opendir(), f_readdir(), f_setlabel(), f_unlink(), and follow_path().

◆ f_chmod()

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

Definition at line 3671 of file ff.c.

3676{
3677 FRESULT res;
3678 DIR dj;
3679 BYTE *dir;
3681
3682
3683 res = find_volume(&dj.fs, &path, 1); /* Get logical drive number */
3684 if (res == FR_OK) {
3685 INIT_BUF(dj);
3686 res = follow_path(&dj, path); /* Follow the file path */
3687 FREE_BUF();
3688 if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
3690 if (res == FR_OK) {
3691 dir = dj.dir;
3692 if (!dir) { /* Is it a root directory? */
3694 } else { /* File or sub directory */
3695 mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */
3696 dir[DIR_Attr] = (attr & mask) | (dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */
3697 dj.fs->wflag = 1;
3698 res = sync_fs(dj.fs);
3699 }
3700 }
3701 }
3702
3703 LEAVE_FF(dj.fs, res);
3704}
static FRESULT find_volume(FATFS **rfs, const TCHAR **path, BYTE wmode)
Definition: ff.c:2203
#define DEFINE_NAMEBUF
Definition: ff.c:473
#define LEAVE_FF(fs, res)
Definition: ff.c:43
#define INIT_BUF(dobj)
Definition: ff.c:474
#define FREE_BUF()
Definition: ff.c:475
static FRESULT sync_fs(FATFS *fs)
Definition: ff.c:760
static FRESULT follow_path(DIR *dp, const TCHAR *path)
Definition: ff.c:2052
#define AM_SYS
Definition: ff.h:318
#define AM_HID
Definition: ff.h:317
#define AM_RDO
Definition: ff.h:316
GLenum GLint GLuint mask
Definition: glext.h:6028
Definition: dirent.h:40
Definition: cookie.c:202

◆ f_close()

FRESULT f_close ( FIL fp)

Definition at line 2857 of file ff.c.

2860{
2861 FRESULT res;
2862
2863
2864#if !_FS_READONLY
2865 res = f_sync(fp); /* Flush cached data */
2866 if (res == FR_OK)
2867#endif
2868 {
2869 res = validate(fp); /* Lock volume */
2870 if (res == FR_OK) {
2871#if _FS_REENTRANT
2872 FATFS *fs = fp->fs;
2873#endif
2874#if _FS_LOCK
2875 res = dec_lock(fp->lockid); /* Decrement file open counter */
2876 if (res == FR_OK)
2877#endif
2878 fp->fs = 0; /* Invalidate file object */
2879#if _FS_REENTRANT
2880 unlock_fs(fs, FR_OK); /* Unlock volume */
2881#endif
2882 }
2883 }
2884 return res;
2885}
static FRESULT validate(void *obj)
Definition: ff.c:2372
FRESULT f_sync(FIL *fp)
Definition: ff.c:2809
Definition: ff.h:78
FATFS * fs
Definition: ff.h:115

Referenced by main().

◆ f_closedir()

FRESULT f_closedir ( DIR dp)

Definition at line 3243 of file ff.c.

3246{
3247 FRESULT res;
3248
3249
3250 res = validate(dp);
3251 if (res == FR_OK) {
3252#if _FS_REENTRANT
3253 FATFS *fs = dp->fs;
3254#endif
3255#if _FS_LOCK
3256 if (dp->lockid) /* Decrement sub-directory open counter */
3257 res = dec_lock(dp->lockid);
3258 if (res == FR_OK)
3259#endif
3260 dp->fs = 0; /* Invalidate directory object */
3261#if _FS_REENTRANT
3262 unlock_fs(fs, FR_OK); /* Unlock volume */
3263#endif
3264 }
3265 return res;
3266}

◆ f_getfree()

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

Definition at line 3404 of file ff.c.

3409{
3410 FRESULT res;
3411 FATFS *fs;
3412 DWORD nfree, clst, sect, stat;
3413 UINT i;
3414 BYTE fat, *p;
3415
3416
3417 /* Get logical drive number */
3418 res = find_volume(fatfs, &path, 0);
3419 fs = *fatfs;
3420 if (res == FR_OK) {
3421 /* If free_clust is valid, return it without full cluster scan */
3422 if (fs->free_clust <= fs->n_fatent - 2) {
3423 *nclst = fs->free_clust;
3424 } else {
3425 /* Get number of free clusters */
3426 fat = fs->fs_type;
3427 nfree = 0;
3428 if (fat == FS_FAT12) { /* Sector unalighed entries: Search FAT via regular routine. */
3429 clst = 2;
3430 do {
3431 stat = get_fat(fs, clst);
3432 if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
3433 if (stat == 1) { res = FR_INT_ERR; break; }
3434 if (stat == 0) nfree++;
3435 } while (++clst < fs->n_fatent);
3436 } else { /* Sector alighed entries: Accelerate the FAT search. */
3437 clst = fs->n_fatent; sect = fs->fatbase;
3438 i = 0; p = 0;
3439 do {
3440 if (!i) {
3441 res = move_window(fs, sect++);
3442 if (res != FR_OK) break;
3443 p = fs->win;
3444 i = SS(fs);
3445 }
3446 if (fat == FS_FAT16) {
3447 if (LD_WORD(p) == 0) nfree++;
3448 p += 2; i -= 2;
3449 } else {
3450 if ((LD_DWORD(p) & 0x0FFFFFFF) == 0) nfree++;
3451 p += 4; i -= 4;
3452 }
3453 } while (--clst);
3454 }
3455 fs->free_clust = nfree; /* free_clust is valid */
3456 fs->fsi_flag |= 1; /* FSInfo is to be updated */
3457 *nclst = nfree; /* Return the free clusters */
3458 }
3459 }
3460 LEAVE_FF(fs, res);
3461}
#define stat
Definition: acwin.h:99
#define FS_FAT16
Definition: ff.h:310
#define FS_FAT12
Definition: ff.h:309
#define fs
Definition: i386-dis.c:444
static unsigned char * fat
Definition: mkdosfs.c:542
Definition: stat.h:55

◆ f_getlabel()

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

Definition at line 3839 of file ff.c.

3844{
3845 FRESULT res;
3846 DIR dj;
3847 UINT i, j;
3848#if _USE_LFN && _LFN_UNICODE
3849 WCHAR w;
3850#endif
3851
3852
3853 /* Get logical drive number */
3854 res = find_volume(&dj.fs, &path, 0);
3855
3856 /* Get volume label */
3857 if (res == FR_OK && label) {
3858 dj.sclust = 0; /* Open root directory */
3859 res = dir_sdi(&dj, 0);
3860 if (res == FR_OK) {
3861 res = dir_read(&dj, 1); /* Get an entry with AM_VOL */
3862 if (res == FR_OK) { /* A volume label is exist */
3863#if _USE_LFN && _LFN_UNICODE
3864 i = j = 0;
3865 do {
3866 w = (i < 11) ? dj.dir[i++] : ' ';
3867 if (IsDBCS1(w) && i < 11 && IsDBCS2(dj.dir[i]))
3868 w = w << 8 | dj.dir[i++];
3869 label[j++] = ff_convert(w, 1); /* OEM -> Unicode */
3870 } while (j < 11);
3871#else
3872 mem_cpy(label, dj.dir, 11);
3873#endif
3874 j = 11;
3875 do {
3876 label[j] = 0;
3877 if (!j) break;
3878 } while (label[--j] == ' ');
3879 }
3880 if (res == FR_NO_FILE) { /* No label, return nul string */
3881 label[0] = 0;
3882 res = FR_OK;
3883 }
3884 }
3885 }
3886
3887 /* Get volume serial number */
3888 if (res == FR_OK && vsn) {
3889 res = move_window(dj.fs, dj.fs->volbase);
3890 if (res == FR_OK) {
3891 i = dj.fs->fs_type == FS_FAT32 ? BS_VolID32 : BS_VolID;
3892 *vsn = LD_DWORD(&dj.fs->win[i]);
3893 }
3894 }
3895
3896 LEAVE_FF(dj.fs, res);
3897}
#define BS_VolID
Definition: ff.c:386
static FRESULT dir_read(DIR *dp, int vol)
Definition: ff.c:1519
#define BS_VolID32
Definition: ff.c:398
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
if(dx< 0)
Definition: linetemp.h:194
static const WCHAR label[]
Definition: itemdlg.c:1546
DWORD volbase
Definition: ff.h:102

◆ f_lseek()

FRESULT f_lseek ( FIL fp,
DWORD  ofs 
)

Definition at line 3029 of file ff.c.

3033{
3034 FRESULT res;
3035 DWORD clst, bcs, nsect, ifptr;
3036#if _USE_FASTSEEK
3037 DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
3038#endif
3039
3040
3041 res = validate(fp); /* Check validity of the object */
3042 if (res != FR_OK) LEAVE_FF(fp->fs, res);
3043 if (fp->err) /* Check error */
3044 LEAVE_FF(fp->fs, (FRESULT)fp->err);
3045
3046#if _USE_FASTSEEK
3047 if (fp->cltbl) { /* Fast seek */
3048 if (ofs == CREATE_LINKMAP) { /* Create CLMT */
3049 tbl = fp->cltbl;
3050 tlen = *tbl++; ulen = 2; /* Given table size and required table size */
3051 cl = fp->sclust; /* Top of the chain */
3052 if (cl) {
3053 do {
3054 /* Get a fragment */
3055 tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */
3056 do {
3057 pcl = cl; ncl++;
3058 cl = get_fat(fp->fs, cl);
3059 if (cl <= 1) ABORT(fp->fs, FR_INT_ERR);
3060 if (cl == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
3061 } while (cl == pcl + 1);
3062 if (ulen <= tlen) { /* Store the length and top of the fragment */
3063 *tbl++ = ncl; *tbl++ = tcl;
3064 }
3065 } while (cl < fp->fs->n_fatent); /* Repeat until end of chain */
3066 }
3067 *fp->cltbl = ulen; /* Number of items used */
3068 if (ulen <= tlen)
3069 *tbl = 0; /* Terminate table */
3070 else
3071 res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */
3072
3073 } else { /* Fast seek */
3074 if (ofs > fp->fsize) /* Clip offset at the file size */
3075 ofs = fp->fsize;
3076 fp->fptr = ofs; /* Set file pointer */
3077 if (ofs) {
3078 fp->clust = clmt_clust(fp, ofs - 1);
3079 dsc = clust2sect(fp->fs, fp->clust);
3080 if (!dsc) ABORT(fp->fs, FR_INT_ERR);
3081 dsc += (ofs - 1) / SS(fp->fs) & (fp->fs->csize - 1);
3082 if (fp->fptr % SS(fp->fs) && dsc != fp->dsect) { /* Refill sector cache if needed */
3083#if !_FS_TINY
3084#if !_FS_READONLY
3085 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
3086 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
3087 ABORT(fp->fs, FR_DISK_ERR);
3088 fp->flag &= ~FA__DIRTY;
3089 }
3090#endif
3091 if (disk_read(fp->fs->drv, fp->buf, dsc, 1) != RES_OK) /* Load current sector */
3092 ABORT(fp->fs, FR_DISK_ERR);
3093#endif
3094 fp->dsect = dsc;
3095 }
3096 }
3097 }
3098 } else
3099#endif
3100
3101 /* Normal Seek */
3102 {
3103 if (ofs > fp->fsize /* In read-only mode, clip offset with the file size */
3104#if !_FS_READONLY
3105 && !(fp->flag & FA_WRITE)
3106#endif
3107 ) ofs = fp->fsize;
3108
3109 ifptr = fp->fptr;
3110 fp->fptr = nsect = 0;
3111 if (ofs) {
3112 bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */
3113 if (ifptr > 0 &&
3114 (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
3115 fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */
3116 ofs -= fp->fptr;
3117 clst = fp->clust;
3118 } else { /* When seek to back cluster, */
3119 clst = fp->sclust; /* start from the first cluster */
3120#if !_FS_READONLY
3121 if (clst == 0) { /* If no cluster chain, create a new chain */
3122 clst = create_chain(fp->fs, 0);
3123 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
3124 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
3125 fp->sclust = clst;
3126 }
3127#endif
3128 fp->clust = clst;
3129 }
3130 if (clst != 0) {
3131 while (ofs > bcs) { /* Cluster following loop */
3132#if !_FS_READONLY
3133 if (fp->flag & FA_WRITE) { /* Check if in write mode or not */
3134 clst = create_chain(fp->fs, clst); /* Force stretch if in write mode */
3135 if (clst == 0) { /* When disk gets full, clip file size */
3136 ofs = bcs; break;
3137 }
3138 } else
3139#endif
3140 clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */
3141 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
3142 if (clst <= 1 || clst >= fp->fs->n_fatent) ABORT(fp->fs, FR_INT_ERR);
3143 fp->clust = clst;
3144 fp->fptr += bcs;
3145 ofs -= bcs;
3146 }
3147 fp->fptr += ofs;
3148 if (ofs % SS(fp->fs)) {
3149 nsect = clust2sect(fp->fs, clst); /* Current sector */
3150 if (!nsect) ABORT(fp->fs, FR_INT_ERR);
3151 nsect += ofs / SS(fp->fs);
3152 }
3153 }
3154 }
3155 if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { /* Fill sector cache if needed */
3156#if !_FS_TINY
3157#if !_FS_READONLY
3158 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
3159 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
3160 ABORT(fp->fs, FR_DISK_ERR);
3161 fp->flag &= ~FA__DIRTY;
3162 }
3163#endif
3164 if (disk_read(fp->fs->drv, fp->buf, nsect, 1) != RES_OK) /* Fill sector cache */
3165 ABORT(fp->fs, FR_DISK_ERR);
3166#endif
3167 fp->dsect = nsect;
3168 }
3169#if !_FS_READONLY
3170 if (fp->fptr > fp->fsize) { /* Set file change flag if the file size is extended */
3171 fp->fsize = fp->fptr;
3172 fp->flag |= FA__WRITTEN;
3173 }
3174#endif
3175 }
3176
3177 LEAVE_FF(fp->fs, res);
3178}
static BOOLEAN disk_read(ULONG DeviceId, u64 physical, void *dest, u32 count)
Definition: btrfs.c:253
@ RES_OK
Definition: diskio.h:23
#define ABORT(fs, res)
Definition: ff.c:46
@ FR_NOT_ENOUGH_CORE
Definition: ff.h:202
#define FA__DIRTY
Definition: ff.h:303
#define FA__WRITTEN
Definition: ff.h:302
#define CREATE_LINKMAP
Definition: ff.h:327
#define FA_WRITE
Definition: ff.h:298
#define _FS_READONLY
Definition: ffconf.h:11
static NTSTATUS disk_write(RDPCLIENT *This, NTHANDLE handle, uint8 *data, uint32 length, uint32 offset, uint32 *result)
Definition: disk.c:585
#define DWORD
Definition: nt_native.h:44
BYTE drv
Definition: ff.h:80
DWORD fptr
Definition: ff.h:119
BYTE buf[_MAX_SS]
Definition: ff.h:135
DWORD fsize
Definition: ff.h:120
DWORD clust
Definition: ff.h:122
DWORD dsect
Definition: ff.h:123
BYTE flag
Definition: ff.h:117
DWORD sclust
Definition: ff.h:121
BYTE err
Definition: ff.h:118

◆ f_mkdir()

FRESULT f_mkdir ( const TCHAR path)

Definition at line 3595 of file ff.c.

3598{
3599 FRESULT res;
3600 DIR dj;
3601 BYTE *dir, n;
3602 DWORD dsc, dcl, pcl, tm = GET_FATTIME();
3604
3605
3606 /* Get logical drive number */
3607 res = find_volume(&dj.fs, &path, 1);
3608 if (res == FR_OK) {
3609 INIT_BUF(dj);
3610 res = follow_path(&dj, path); /* Follow the file path */
3611 if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */
3612 if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT))
3614 if (res == FR_NO_FILE) { /* Can create a new directory */
3615 dcl = create_chain(dj.fs, 0); /* Allocate a cluster for the new directory table */
3616 res = FR_OK;
3617 if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
3618 if (dcl == 1) res = FR_INT_ERR;
3619 if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
3620 if (res == FR_OK) /* Flush FAT */
3621 res = sync_window(dj.fs);
3622 if (res == FR_OK) { /* Initialize the new directory table */
3623 dsc = clust2sect(dj.fs, dcl);
3624 dir = dj.fs->win;
3625 mem_set(dir, 0, SS(dj.fs));
3626 mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */
3627 dir[DIR_Name] = '.';
3628 dir[DIR_Attr] = AM_DIR;
3631 st_clust(dir, dcl);
3632 mem_cpy(dir + SZ_DIRE, dir, SZ_DIRE); /* Create ".." entry */
3633 dir[SZ_DIRE + 1] = '.'; pcl = dj.sclust;
3634 if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
3635 pcl = 0;
3636 st_clust(dir + SZ_DIRE, pcl);
3637 for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */
3638 dj.fs->winsect = dsc++;
3639 dj.fs->wflag = 1;
3640 res = sync_window(dj.fs);
3641 if (res != FR_OK) break;
3642 mem_set(dir, 0, SS(dj.fs));
3643 }
3644 }
3645 if (res == FR_OK) res = dir_register(&dj); /* Register the object to the directoy */
3646 if (res != FR_OK) {
3647 remove_chain(dj.fs, dcl); /* Could not register, remove cluster chain */
3648 } else {
3649 dir = dj.dir;
3650 dir[DIR_Attr] = AM_DIR; /* Attribute */
3651 ST_DWORD(dir + DIR_CrtTime, tm); /* Created time */
3652 ST_DWORD(dir + DIR_WrtTime, tm); /* Modified time */
3653 st_clust(dir, dcl); /* Table start cluster */
3654 dj.fs->wflag = 1;
3655 res = sync_fs(dj.fs);
3656 }
3657 }
3658 FREE_BUF();
3659 }
3660
3661 LEAVE_FF(dj.fs, res);
3662}
static void st_clust(BYTE *dir, DWORD cl)
Definition: ff.c:1252
#define DIR_CrtTime
Definition: ff.c:413
#define GET_FATTIME()
Definition: ff.c:67
static FRESULT dir_register(DIR *dp)
Definition: ff.c:1578
static FRESULT remove_chain(FATFS *fs, DWORD clst)
Definition: ff.c:937
#define DIR_WrtTime
Definition: ff.c:417
#define AM_DIR
Definition: ff.h:321
@ FR_EXIST
Definition: ff.h:193
#define ST_DWORD(ptr, val)
Definition: ff.h:343
Definition: time.h:68

Referenced by main().

◆ f_mkfs()

FRESULT f_mkfs ( const TCHAR path,
BYTE  sfd,
UINT  au 
)

Definition at line 4068 of file ff.c.

4073{
4074 static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0};
4075 static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
4076 int vol;
4077 BYTE fmt, md, sys, *tbl, pdrv, part;
4078 DWORD n_clst, vs, n, wsect;
4079 UINT i;
4080 DWORD b_vol, b_fat, b_dir, b_data; /* LBA */
4081 DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */
4082 FATFS *fs;
4083 DSTATUS stat;
4084#if _USE_TRIM
4085 DWORD eb[2];
4086#endif
4087
4088
4089 /* Check mounted drive and clear work area */
4090 if (sfd > 1) return FR_INVALID_PARAMETER;
4091 vol = get_ldnumber(&path);
4092 if (vol < 0) return FR_INVALID_DRIVE;
4093 fs = FatFs[vol];
4094 if (!fs) return FR_NOT_ENABLED;
4095 fs->fs_type = 0;
4096 pdrv = LD2PD(vol); /* Physical drive */
4097 part = LD2PT(vol); /* Partition (0:auto detect, 1-4:get from partition table)*/
4098
4099 /* Get disk statics */
4100 stat = disk_initialize(pdrv);
4101 if (stat & STA_NOINIT) return FR_NOT_READY;
4102 if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
4103#if _MAX_SS != _MIN_SS /* Get disk sector size */
4104 if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS || SS(fs) < _MIN_SS)
4105 return FR_DISK_ERR;
4106#endif
4107 if (_MULTI_PARTITION && part) {
4108 /* Get partition information from partition table in the MBR */
4109 if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
4110 if (LD_WORD(fs->win + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
4111 tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
4112 if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */
4113 b_vol = LD_DWORD(tbl + 8); /* Volume start sector */
4114 n_vol = LD_DWORD(tbl + 12); /* Volume size */
4115 } else {
4116 /* Create a partition in this function */
4117 if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
4118 return FR_DISK_ERR;
4119 b_vol = (sfd) ? 0 : 63; /* Volume start sector */
4120 n_vol -= b_vol; /* Volume size */
4121 }
4122
4123 if (au & (au - 1)) au = 0;
4124 if (!au) { /* AU auto selection */
4125 vs = n_vol / (2000 / (SS(fs) / 512));
4126 for (i = 0; vs < vst[i]; i++) ;
4127 au = cst[i];
4128 }
4129 if (au >= _MIN_SS) au /= SS(fs); /* Number of sectors per cluster */
4130 if (!au) au = 1;
4131 if (au > 128) au = 128;
4132
4133 /* Pre-compute number of clusters and FAT sub-type */
4134 n_clst = n_vol / au;
4135 fmt = FS_FAT12;
4136 if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
4137 if (n_clst >= MIN_FAT32) fmt = FS_FAT32;
4138
4139 /* Determine offset and size of FAT structure */
4140 if (fmt == FS_FAT32) {
4141 n_fat = ((n_clst * 4) + 8 + SS(fs) - 1) / SS(fs);
4142 n_rsv = 32;
4143 n_dir = 0;
4144 } else {
4145 n_fat = (fmt == FS_FAT12) ? (n_clst * 3 + 1) / 2 + 3 : (n_clst * 2) + 4;
4146 n_fat = (n_fat + SS(fs) - 1) / SS(fs);
4147 n_rsv = 1;
4148 if (fmt == FS_FAT12)
4149 n_dir = (DWORD)N_ROOTDIR12 * SZ_DIRE / SS(fs);
4150 else
4151 n_dir = (DWORD)N_ROOTDIR16 * SZ_DIRE / SS(fs);
4152 }
4153 b_fat = b_vol + n_rsv; /* FAT area start sector */
4154 b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */
4155 b_data = b_dir + n_dir; /* Data area start sector */
4156 if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */
4157
4158 /* Align data start sector to erase block boundary (for flash memory media) */
4159 if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
4160 n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */
4161 n = (n - b_data) / N_FATS;
4162 if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */
4163 n_rsv += n;
4164 b_fat += n;
4165 } else if (fmt == FS_FAT16) { /* FAT16: Expand FAT size */
4166 n_fat += n;
4167 } // else /* if (fmt == FS_FAT12) */ {} /* FAT12: Do nothing */
4168
4169 /* Determine number of clusters and final check of validity of the FAT sub-type */
4170 n_clst = (n_vol - n_rsv - n_fat * N_FATS - n_dir) / au;
4171 if ( (fmt == FS_FAT16 && n_clst < MIN_FAT16)
4172 || (fmt == FS_FAT32 && n_clst < MIN_FAT32))
4173 return FR_MKFS_ABORTED;
4174
4175 /* Determine system ID in the partition table */
4176 if (fmt == FS_FAT32) {
4177 sys = 0x0C; /* FAT32X */
4178 } else {
4179 if (fmt == FS_FAT12 && n_vol < 0x10000) {
4180 sys = 0x01; /* FAT12(<65536) */
4181 } else {
4182 sys = (n_vol < 0x10000) ? 0x04 : 0x06; /* FAT16(<65536) : FAT12/16(>=65536) */
4183 }
4184 }
4185
4186 if (_MULTI_PARTITION && part) {
4187 /* Update system ID in the partition table */
4188 tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
4189 tbl[4] = sys;
4190 if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to teh MBR */
4191 return FR_DISK_ERR;
4192 md = 0xF8;
4193 } else {
4194 if (sfd) { /* No partition table (SFD) */
4195 md = 0xF0;
4196 } else { /* Create partition table (FDISK) */
4197 mem_set(fs->win, 0, SS(fs));
4198 tbl = fs->win + MBR_Table; /* Create partition table for single partition in the drive */
4199 tbl[1] = 1; /* Partition start head */
4200 tbl[2] = 1; /* Partition start sector */
4201 tbl[3] = 0; /* Partition start cylinder */
4202 tbl[4] = sys; /* System type */
4203 tbl[5] = 254; /* Partition end head */
4204 n = (b_vol + n_vol) / 63 / 255;
4205 tbl[6] = (BYTE)(n >> 2 | 63); /* Partition end sector */
4206 tbl[7] = (BYTE)n; /* End cylinder */
4207 ST_DWORD(tbl + 8, 63); /* Partition start in LBA */
4208 ST_DWORD(tbl + 12, n_vol); /* Partition size in LBA */
4209 ST_WORD(fs->win + BS_55AA, 0xAA55); /* MBR signature */
4210 if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR */
4211 return FR_DISK_ERR;
4212 md = 0xF8;
4213 }
4214 }
4215
4216 /* Create BPB in the VBR */
4217 tbl = fs->win; /* Clear sector */
4218 mem_set(tbl, 0, SS(fs));
4219 mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
4220 i = SS(fs); /* Sector size */
4221 ST_WORD(tbl + BPB_BytsPerSec, i);
4222 tbl[BPB_SecPerClus] = (BYTE)au; /* Sectors per cluster */
4223 ST_WORD(tbl + BPB_RsvdSecCnt, n_rsv); /* Reserved sectors */
4224 tbl[BPB_NumFATs] = N_FATS; /* Number of FATs */
4225 i = (fmt == FS_FAT32) ? 0 : (fmt == FS_FAT12 ? N_ROOTDIR12 : N_ROOTDIR16); /* Number of root directory entries */
4226 ST_WORD(tbl + BPB_RootEntCnt, i);
4227 if (n_vol < 0x10000) { /* Number of total sectors */
4228 ST_WORD(tbl + BPB_TotSec16, n_vol);
4229 } else {
4230 ST_DWORD(tbl + BPB_TotSec32, n_vol);
4231 }
4232 tbl[BPB_Media] = md; /* Media descriptor */
4233 ST_DWORD(tbl + BPB_HiddSec, b_vol); /* Hidden sectors */
4234 n = GET_FATTIME(); /* Use current time as VSN */
4235 if (fmt == FS_FAT32) {
4236 ST_WORD(tbl + BPB_SecPerTrk, 63); /* Number of sectors per track */
4237 ST_WORD(tbl + BPB_NumHeads, 255); /* Number of heads */
4238 ST_DWORD(tbl + BS_VolID32, n); /* VSN */
4239 ST_DWORD(tbl + BPB_FATSz32, n_fat); /* Number of sectors per FAT */
4240 ST_DWORD(tbl + BPB_RootClus, 2); /* Root directory start cluster (2) */
4241 ST_WORD(tbl + BPB_FSInfo, 1); /* FSINFO record offset (VBR + 1) */
4242 ST_WORD(tbl + BPB_BkBootSec, 6); /* Backup boot record offset (VBR + 6) */
4243 tbl[BS_DrvNum32] = 0x80; /* Drive number */
4244 tbl[BS_BootSig32] = 0x29; /* Extended boot signature */
4245 mem_cpy(tbl + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */
4246 } else if (fmt == FS_FAT16) {
4247 ST_WORD(tbl + BPB_SecPerTrk, 63); /* Number of sectors per track */
4248 ST_WORD(tbl + BPB_NumHeads, 255); /* Number of heads */
4249 ST_DWORD(tbl + BS_VolID, n); /* VSN */
4250 ST_WORD(tbl + BPB_FATSz16, n_fat); /* Number of sectors per FAT */
4251 tbl[BS_DrvNum] = 0x80; /* Drive number */
4252 tbl[BS_BootSig] = 0x29; /* Extended boot signature */
4253 mem_cpy(tbl + BS_VolLab, "NO NAME " "FAT16 ", 19); /* Volume label, FAT signature */
4254 } else /* if (fmt == FS_FAT12) */ {
4255 /* Assume floppy characteristics */
4256 ST_WORD(tbl + BPB_SecPerTrk, 0x12); /* Number of sectors per track */
4257 ST_WORD(tbl + BPB_NumHeads, 0x02); /* Number of heads */
4258 ST_DWORD(tbl + BS_VolID, n); /* VSN */
4259 ST_WORD(tbl + BPB_FATSz16, n_fat); /* Number of sectors per FAT */
4260 tbl[BS_DrvNum] = 0x00; /* Drive number */
4261 tbl[BS_BootSig] = 0x29; /* Extended boot signature */
4262 mem_cpy(tbl + BS_VolLab, "NO NAME " "FAT12 ", 19); /* Volume label, FAT signature */
4263 }
4264 ST_WORD(tbl + BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */
4265 if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */
4266 return FR_DISK_ERR;
4267 if (fmt == FS_FAT32) /* Write it to the backup VBR if needed (VBR + 6) */
4268 disk_write(pdrv, tbl, b_vol + 6, 1);
4269
4270 /* Initialize FAT area */
4271 wsect = b_fat;
4272 for (i = 0; i < N_FATS; i++) { /* Initialize each FAT copy */
4273 mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */
4274 n = md; /* Media descriptor byte */
4275 if (fmt != FS_FAT32) {
4276 n |= (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00;
4277 ST_DWORD(tbl + 0, n); /* Reserve cluster #0-1 (FAT12/16) */
4278 } else {
4279 n |= 0xFFFFFF00;
4280 ST_DWORD(tbl + 0, n); /* Reserve cluster #0-1 (FAT32) */
4281 ST_DWORD(tbl + 4, 0xFFFFFFFF);
4282 ST_DWORD(tbl + 8, 0x0FFFFFFF); /* Reserve cluster #2 for root directory */
4283 }
4284 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
4285 return FR_DISK_ERR;
4286 mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */
4287 for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */
4288 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
4289 return FR_DISK_ERR;
4290 }
4291 }
4292
4293 /* Initialize root directory */
4294 i = (fmt == FS_FAT32) ? au : (UINT)n_dir;
4295 do {
4296 if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
4297 return FR_DISK_ERR;
4298 } while (--i);
4299
4300#if _USE_TRIM /* Erase data area if needed */
4301 {
4302 eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
4303 disk_ioctl(pdrv, CTRL_TRIM, eb);
4304 }
4305#endif
4306
4307 /* Create FSINFO if needed */
4308 if (fmt == FS_FAT32) {
4309 ST_DWORD(tbl + FSI_LeadSig, 0x41615252);
4310 ST_DWORD(tbl + FSI_StrucSig, 0x61417272);
4311 ST_DWORD(tbl + FSI_Free_Count, n_clst - 1); /* Number of free clusters */
4312 ST_DWORD(tbl + FSI_Nxt_Free, 2); /* Last allocated cluster# */
4313 ST_WORD(tbl + BS_55AA, 0xAA55);
4314 disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR + 1) */
4315 disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR + 7) */
4316 }
4317
4318 return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
4319}
#define md
Definition: compat-1.3.h:2013
DSTATUS disk_initialize(BYTE pdrv)
Definition: diskio.c:66
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
Definition: diskio.c:169
#define CTRL_SYNC
Definition: diskio.h:54
#define GET_SECTOR_COUNT
Definition: diskio.h:55
#define STA_PROTECT
Definition: diskio.h:48
#define STA_NOINIT
Definition: diskio.h:46
#define GET_SECTOR_SIZE
Definition: diskio.h:56
BYTE DSTATUS
Definition: diskio.h:19
#define GET_BLOCK_SIZE
Definition: diskio.h:57
#define CTRL_TRIM
Definition: diskio.h:58
#define N_ROOTDIR12
Definition: ff.c:4063
#define BS_DrvNum
Definition: ff.c:383
#define BS_VolLab
Definition: ff.c:387
#define FSI_LeadSig
Definition: ff.c:401
#define FSI_Nxt_Free
Definition: ff.c:404
#define BPB_BkBootSec
Definition: ff.c:394
#define FSI_StrucSig
Definition: ff.c:402
static FATFS * FatFs[_VOLUMES]
Definition: ff.c:448
#define N_FATS
Definition: ff.c:4065
#define BPB_Media
Definition: ff.c:377
#define BPB_HiddSec
Definition: ff.c:381
#define MIN_FAT32
Definition: ff.c:362
#define BPB_TotSec16
Definition: ff.c:376
#define BPB_FSInfo
Definition: ff.c:393
#define BS_BootSig32
Definition: ff.c:397
#define BPB_FATSz16
Definition: ff.c:378
#define BPB_FATSz32
Definition: ff.c:389
#define BPB_TotSec32
Definition: ff.c:382
#define BPB_RootClus
Definition: ff.c:392
#define BS_VolLab32
Definition: ff.c:399
#define BPB_BytsPerSec
Definition: ff.c:371
#define BS_BootSig
Definition: ff.c:385
static int get_ldnumber(const TCHAR **path)
Definition: ff.c:2114
#define BPB_NumHeads
Definition: ff.c:380
#define BS_DrvNum32
Definition: ff.c:395
#define BPB_RootEntCnt
Definition: ff.c:375
#define BPB_SecPerClus
Definition: ff.c:372
#define BPB_RsvdSecCnt
Definition: ff.c:373
#define FSI_Free_Count
Definition: ff.c:403
#define MBR_Table
Definition: ff.c:405
#define BPB_SecPerTrk
Definition: ff.c:379
#define N_ROOTDIR16
Definition: ff.c:4064
#define MIN_FAT16
Definition: ff.c:361
#define SZ_PTE
Definition: ff.c:406
#define BPB_NumFATs
Definition: ff.c:374
@ FR_INVALID_PARAMETER
Definition: ff.h:204
@ FR_INVALID_DRIVE
Definition: ff.h:196
@ FR_MKFS_ABORTED
Definition: ff.h:199
@ FR_WRITE_PROTECTED
Definition: ff.h:195
@ FR_NOT_READY
Definition: ff.h:188
@ FR_NOT_ENABLED
Definition: ff.h:197
#define LD2PD(vol)
Definition: ff.h:46
#define ST_WORD(ptr, val)
Definition: ff.h:342
#define LD2PT(vol)
Definition: ff.h:47
#define _MAX_SS
Definition: ffconf.h:163
#define _MIN_SS
Definition: ffconf.h:162
#define _MULTI_PARTITION
Definition: ffconf.h:154
static vector_t * vs
Definition: server.c:127
Definition: dsound.c:943

Referenced by main().

◆ f_mount()

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

Definition at line 2402 of file ff.c.

2407{
2408 FATFS *cfs;
2409 int vol;
2410 FRESULT res;
2411 const TCHAR *rp = path;
2412
2413
2414 vol = get_ldnumber(&rp);
2415 if (vol < 0) return FR_INVALID_DRIVE;
2416 cfs = FatFs[vol]; /* Pointer to fs object */
2417
2418 if (cfs) {
2419#if _FS_LOCK
2420 clear_lock(cfs);
2421#endif
2422#if _FS_REENTRANT /* Discard sync object of the current volume */
2423 if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR;
2424#endif
2425 cfs->fs_type = 0; /* Clear old fs object */
2426 }
2427
2428 if (fs) {
2429 fs->fs_type = 0; /* Clear new fs object */
2430#if _FS_REENTRANT /* Create sync object for the new volume */
2431 if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR;
2432#endif
2433 }
2434 FatFs[vol] = fs; /* Register new fs object */
2435
2436 if (!fs || opt != 1) return FR_OK; /* Do not mount now, it will be mounted later */
2437
2438 res = find_volume(&fs, &path, 0); /* Force mounted the volume */
2439 LEAVE_FF(fs, res);
2440}

Referenced by need_mount().

◆ f_open()

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

Definition at line 2449 of file ff.c.

2454{
2455 FRESULT res;
2456 DIR dj;
2457 BYTE *dir;
2459#if !_FS_READONLY
2460 DWORD dw, cl;
2461#endif
2462
2463
2464 if (!fp) return FR_INVALID_OBJECT;
2465 fp->fs = 0; /* Clear file object */
2466
2467 /* Get logical drive number */
2468#if !_FS_READONLY
2470 res = find_volume(&dj.fs, &path, (BYTE)(mode & ~FA_READ));
2471#else
2472 mode &= FA_READ;
2473 res = find_volume(&dj.fs, &path, 0);
2474#endif
2475 if (res == FR_OK) {
2476 INIT_BUF(dj);
2477 res = follow_path(&dj, path); /* Follow the file path */
2478 dir = dj.dir;
2479#if !_FS_READONLY /* R/W configuration */
2480 if (res == FR_OK) {
2481 if (!dir) /* Default directory itself */
2483#if _FS_LOCK
2484 else
2485 res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
2486#endif
2487 }
2488 /* Create or Open a file */
2490 if (res != FR_OK) { /* No file, create new */
2491 if (res == FR_NO_FILE) /* There is no file to open, create a new entry */
2492#if _FS_LOCK
2493 res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
2494#else
2495 res = dir_register(&dj);
2496#endif
2497 mode |= FA_CREATE_ALWAYS; /* File is created */
2498 dir = dj.dir; /* New entry */
2499 }
2500 else { /* Any object is already existing */
2501 if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */
2502 res = FR_DENIED;
2503 } else {
2504 if (mode & FA_CREATE_NEW) /* Cannot create as new file */
2505 res = FR_EXIST;
2506 }
2507 }
2508 if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */
2509 dw = GET_FATTIME();
2510 ST_DWORD(dir + DIR_CrtTime, dw);/* Set created time */
2511 ST_DWORD(dir + DIR_WrtTime, dw);/* Set modified time */
2512 dir[DIR_Attr] = 0; /* Reset attribute */
2513 ST_DWORD(dir + DIR_FileSize, 0);/* Reset file size */
2514 cl = ld_clust(dj.fs, dir); /* Get cluster chain */
2515 st_clust(dir, 0); /* Reset cluster */
2516 dj.fs->wflag = 1;
2517 if (cl) { /* Remove the cluster chain if exist */
2518 dw = dj.fs->winsect;
2519 res = remove_chain(dj.fs, cl);
2520 if (res == FR_OK) {
2521 dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */
2522 res = move_window(dj.fs, dw);
2523 }
2524 }
2525 }
2526 }
2527 else { /* Open an existing file */
2528 if (res == FR_OK) { /* Following succeeded */
2529 if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */
2530 res = FR_NO_FILE;
2531 } else {
2532 if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
2533 res = FR_DENIED;
2534 }
2535 }
2536 }
2537 if (res == FR_OK) {
2538 if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */
2539 mode |= FA__WRITTEN;
2540 fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */
2541 fp->dir_ptr = dir;
2542#if _FS_LOCK
2543 fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
2544 if (!fp->lockid) res = FR_INT_ERR;
2545#endif
2546 }
2547
2548#else /* R/O configuration */
2549 if (res == FR_OK) { /* Follow succeeded */
2550 dir = dj.dir;
2551 if (!dir) { /* Current directory itself */
2553 } else {
2554 if (dir[DIR_Attr] & AM_DIR) /* It is a directory */
2555 res = FR_NO_FILE;
2556 }
2557 }
2558#endif
2559 FREE_BUF();
2560
2561 if (res == FR_OK) {
2562 fp->flag = mode; /* File access mode */
2563 fp->err = 0; /* Clear error flag */
2564 fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */
2565 fp->fsize = LD_DWORD(dir + DIR_FileSize); /* File size */
2566 fp->fptr = 0; /* File pointer */
2567 fp->dsect = 0;
2568#if _USE_FASTSEEK
2569 fp->cltbl = 0; /* Normal seek mode */
2570#endif
2571 fp->fs = dj.fs; /* Validate file object */
2572 fp->id = fp->fs->id;
2573 }
2574 }
2575
2576 LEAVE_FF(dj.fs, res);
2577}
#define DIR_FileSize
Definition: ff.c:420
static DWORD ld_clust(FATFS *fs, const BYTE *dir)
Definition: ff.c:1235
#define FA_OPEN_ALWAYS
Definition: ff.h:301
#define FA_READ
Definition: ff.h:294
#define FA_CREATE_NEW
Definition: ff.h:299
@ FR_INVALID_OBJECT
Definition: ff.h:194
@ FR_TOO_MANY_OPEN_FILES
Definition: ff.h:203
#define FA_CREATE_ALWAYS
Definition: ff.h:300
GLenum mode
Definition: glext.h:6217
REFIID LPVOID DWORD_PTR dw
Definition: atlbase.h:40
WORD id
Definition: ff.h:85
DWORD last_clust
Definition: ff.h:94
BYTE * dir_ptr
Definition: ff.h:126
DWORD dir_sect
Definition: ff.h:125
WORD id
Definition: ff.h:116

Referenced by main().

◆ f_opendir()

FRESULT f_opendir ( DIR dp,
const TCHAR path 
)

Definition at line 3187 of file ff.c.

3191{
3192 FRESULT res;
3193 FATFS* fs;
3195
3196
3197 if (!dp) return FR_INVALID_OBJECT;
3198
3199 /* Get logical drive number */
3200 res = find_volume(&fs, &path, 0);
3201 if (res == FR_OK) {
3202 dp->fs = fs;
3203 INIT_BUF(*dp);
3204 res = follow_path(dp, path); /* Follow the path to the directory */
3205 FREE_BUF();
3206 if (res == FR_OK) { /* Follow completed */
3207 if (dp->dir) { /* It is not the origin directory itself */
3208 if (dp->dir[DIR_Attr] & AM_DIR) /* The object is a sub directory */
3209 dp->sclust = ld_clust(fs, dp->dir);
3210 else /* The object is a file */
3211 res = FR_NO_PATH;
3212 }
3213 if (res == FR_OK) {
3214 dp->id = fs->id;
3215 res = dir_sdi(dp, 0); /* Rewind directory */
3216#if _FS_LOCK
3217 if (res == FR_OK) {
3218 if (dp->sclust) {
3219 dp->lockid = inc_lock(dp, 0); /* Lock the sub directory */
3220 if (!dp->lockid)
3222 } else {
3223 dp->lockid = 0; /* Root directory need not to be locked */
3224 }
3225 }
3226#endif
3227 }
3228 }
3229 if (res == FR_NO_FILE) res = FR_NO_PATH;
3230 }
3231 if (res != FR_OK) dp->fs = 0; /* Invalidate the directory object if function faild */
3232
3233 LEAVE_FF(fs, res);
3234}
@ FR_NO_PATH
Definition: ff.h:190
WORD id
Definition: ff.h:145

Referenced by main().

◆ f_read()

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

Definition at line 2586 of file ff.c.

2592{
2593 FRESULT res;
2594 DWORD clst, sect, remain;
2595 UINT rcnt, cc;
2596 BYTE csect, *rbuff = (BYTE*)buff;
2597
2598
2599 *br = 0; /* Clear read byte counter */
2600
2601 res = validate(fp); /* Check validity */
2602 if (res != FR_OK) LEAVE_FF(fp->fs, res);
2603 if (fp->err) /* Check error */
2604 LEAVE_FF(fp->fs, (FRESULT)fp->err);
2605 if (!(fp->flag & FA_READ)) /* Check access mode */
2606 LEAVE_FF(fp->fs, FR_DENIED);
2607 remain = fp->fsize - fp->fptr;
2608 if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
2609
2610 for ( ; btr; /* Repeat until all data read */
2611 rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) {
2612 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
2613 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
2614 if (!csect) { /* On the cluster boundary? */
2615 if (fp->fptr == 0) { /* On the top of the file? */
2616 clst = fp->sclust; /* Follow from the origin */
2617 } else { /* Middle or end of the file */
2618#if _USE_FASTSEEK
2619 if (fp->cltbl)
2620 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
2621 else
2622#endif
2623 clst = get_fat(fp->fs, fp->clust); /* Follow cluster chain on the FAT */
2624 }
2625 if (clst < 2) ABORT(fp->fs, FR_INT_ERR);
2626 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
2627 fp->clust = clst; /* Update current cluster */
2628 }
2629 sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
2630 if (!sect) ABORT(fp->fs, FR_INT_ERR);
2631 sect += csect;
2632 cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */
2633 if (cc) { /* Read maximum contiguous sectors directly */
2634 if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
2635 cc = fp->fs->csize - csect;
2636 if (disk_read(fp->fs->drv, rbuff, sect, cc) != RES_OK)
2637 ABORT(fp->fs, FR_DISK_ERR);
2638#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
2639#if _FS_TINY
2640 if (fp->fs->wflag && fp->fs->winsect - sect < cc)
2641 mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs));
2642#else
2643 if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc)
2644 mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs));
2645#endif
2646#endif
2647 rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
2648 continue;
2649 }
2650#if !_FS_TINY
2651 if (fp->dsect != sect) { /* Load data sector if not in cache */
2652#if !_FS_READONLY
2653 if (fp->flag & FA__DIRTY) { /* Write-back dirty sector cache */
2654 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
2655 ABORT(fp->fs, FR_DISK_ERR);
2656 fp->flag &= ~FA__DIRTY;
2657 }
2658#endif
2659 if (disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK) /* Fill sector cache */
2660 ABORT(fp->fs, FR_DISK_ERR);
2661 }
2662#endif
2663 fp->dsect = sect;
2664 }
2665 rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */
2666 if (rcnt > btr) rcnt = btr;
2667#if _FS_TINY
2668 if (move_window(fp->fs, fp->dsect) != FR_OK) /* Move sector window */
2669 ABORT(fp->fs, FR_DISK_ERR);
2670 mem_cpy(rbuff, &fp->fs->win[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
2671#else
2672 mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */
2673#endif
2674 }
2675
2676 LEAVE_FF(fp->fs, FR_OK);
2677}
static unsigned char buff[32768]
Definition: fatten.c:17
uint32_t cc
Definition: isohybrid.c:75

Referenced by main().

◆ f_readdir()

FRESULT f_readdir ( DIR dp,
FILINFO fno 
)

Definition at line 3275 of file ff.c.

3279{
3280 FRESULT res;
3282
3283
3284 res = validate(dp); /* Check validity of the object */
3285 if (res == FR_OK) {
3286 if (!fno) {
3287 res = dir_sdi(dp, 0); /* Rewind the directory object */
3288 } else {
3289 INIT_BUF(*dp);
3290 res = dir_read(dp, 0); /* Read an item */
3291 if (res == FR_NO_FILE) { /* Reached end of directory */
3292 dp->sect = 0;
3293 res = FR_OK;
3294 }
3295 if (res == FR_OK) { /* A valid entry is found */
3296 get_fileinfo(dp, fno); /* Get the object information */
3297 res = dir_next(dp, 0); /* Increment index for next */
3298 if (res == FR_NO_FILE) {
3299 dp->sect = 0;
3300 res = FR_OK;
3301 }
3302 }
3303 FREE_BUF();
3304 }
3305 }
3306
3307 LEAVE_FF(dp->fs, res);
3308}
static void get_fileinfo(DIR *dp, FILINFO *fno)
Definition: ff.c:1703

Referenced by main().

◆ f_rename()

FRESULT f_rename ( const TCHAR path_old,
const TCHAR path_new 
)

Definition at line 3713 of file ff.c.

3717{
3718 FRESULT res;
3719 DIR djo, djn;
3720 BYTE buf[21], *dir;
3721 DWORD dw;
3723
3724
3725 /* Get logical drive number of the source object */
3726 res = find_volume(&djo.fs, &path_old, 1);
3727 if (res == FR_OK) {
3728 djn.fs = djo.fs;
3729 INIT_BUF(djo);
3730 res = follow_path(&djo, path_old); /* Check old object */
3731 if (_FS_RPATH && res == FR_OK && (djo.fn[NSFLAG] & NS_DOT))
3733#if _FS_LOCK
3734 if (res == FR_OK) res = chk_lock(&djo, 2);
3735#endif
3736 if (res == FR_OK) { /* Old object is found */
3737 if (!djo.dir) { /* Is root dir? */
3738 res = FR_NO_FILE;
3739 } else {
3740 mem_cpy(buf, djo.dir + DIR_Attr, 21); /* Save information about object except name */
3741 mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */
3742 if (get_ldnumber(&path_new) >= 0) /* Snip drive number off and ignore it */
3743 res = follow_path(&djn, path_new); /* and make sure if new object name is not conflicting */
3744 else
3746 if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */
3747 if (res == FR_NO_FILE) { /* It is a valid path and no name collision */
3748 res = dir_register(&djn); /* Register the new entry */
3749 if (res == FR_OK) {
3750/* Start of critical section where any interruption can cause a cross-link */
3751 dir = djn.dir; /* Copy information about object except name */
3752 mem_cpy(dir + 13, buf + 2, 19);
3753 dir[DIR_Attr] = buf[0] | AM_ARC;
3754 djo.fs->wflag = 1;
3755 if ((dir[DIR_Attr] & AM_DIR) && djo.sclust != djn.sclust) { /* Update .. entry in the sub-directory if needed */
3756 dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
3757 if (!dw) {
3758 res = FR_INT_ERR;
3759 } else {
3760 res = move_window(djo.fs, dw);
3761 dir = djo.fs->win + SZ_DIRE * 1; /* Ptr to .. entry */
3762 if (res == FR_OK && dir[1] == '.') {
3763 st_clust(dir, djn.sclust);
3764 djo.fs->wflag = 1;
3765 }
3766 }
3767 }
3768 if (res == FR_OK) {
3769 res = dir_remove(&djo); /* Remove old entry */
3770 if (res == FR_OK)
3771 res = sync_fs(djo.fs);
3772 }
3773/* End of critical section */
3774 }
3775 }
3776 }
3777 }
3778 FREE_BUF();
3779 }
3780
3781 LEAVE_FF(djo.fs, res);
3782}
static FRESULT dir_remove(DIR *dp)
Definition: ff.c:1656
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751

Referenced by main().

◆ f_setlabel()

FRESULT f_setlabel ( const TCHAR label)

Definition at line 3906 of file ff.c.

3909{
3910 FRESULT res;
3911 DIR dj;
3912 BYTE vn[11];
3913 UINT i, j, sl;
3914 WCHAR w;
3915 DWORD tm;
3916
3917
3918 /* Get logical drive number */
3919 res = find_volume(&dj.fs, &label, 1);
3920 if (res) LEAVE_FF(dj.fs, res);
3921
3922 /* Create a volume label in directory form */
3923 vn[0] = 0;
3924 for (sl = 0; label[sl]; sl++) ; /* Get name length */
3925 for ( ; sl && label[sl - 1] == ' '; sl--) ; /* Remove trailing spaces */
3926 if (sl) { /* Create volume label in directory form */
3927 i = j = 0;
3928 do {
3929#if _USE_LFN && _LFN_UNICODE
3930 w = ff_convert(ff_wtoupper(label[i++]), 0);
3931#else
3932 w = (BYTE)label[i++];
3933 if (IsDBCS1(w))
3934 w = (j < 10 && i < sl && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0;
3935#if _USE_LFN
3936 w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0);
3937#else
3938 if (IsLower(w)) w -= 0x20; /* To upper ASCII characters */
3939#ifdef _EXCVT
3940 if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */
3941#else
3942 if (!_DF1S && w >= 0x80) w = 0; /* Reject extended characters (ASCII cfg) */
3943#endif
3944#endif
3945#endif
3946 if (!w || chk_chr("\"*+,.:;<=>\?[]|\x7F", w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid characters for volume label */
3948 if (w >= 0x100) vn[j++] = (BYTE)(w >> 8);
3949 vn[j++] = (BYTE)w;
3950 } while (i < sl);
3951 while (j < 11) vn[j++] = ' '; /* Fill remaining name field */
3952 if (vn[0] == DDEM) LEAVE_FF(dj.fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */
3953 }
3954
3955 /* Set volume label */
3956 dj.sclust = 0; /* Open root directory */
3957 res = dir_sdi(&dj, 0);
3958 if (res == FR_OK) {
3959 res = dir_read(&dj, 1); /* Get an entry with AM_VOL */
3960 if (res == FR_OK) { /* A volume label is found */
3961 if (vn[0]) {
3962 mem_cpy(dj.dir, vn, 11); /* Change the volume label name */
3963 tm = GET_FATTIME();
3964 ST_DWORD(dj.dir + DIR_CrtTime, tm);
3965 ST_DWORD(dj.dir + DIR_WrtTime, tm);
3966 } else {
3967 dj.dir[0] = DDEM; /* Remove the volume label */
3968 }
3969 dj.fs->wflag = 1;
3970 res = sync_fs(dj.fs);
3971 } else { /* No volume label is found or error */
3972 if (res == FR_NO_FILE) {
3973 res = FR_OK;
3974 if (vn[0]) { /* Create volume label as new */
3975 res = dir_alloc(&dj, 1); /* Allocate an entry for volume label */
3976 if (res == FR_OK) {
3977 mem_set(dj.dir, 0, SZ_DIRE); /* Set volume label */
3978 mem_cpy(dj.dir, vn, 11);
3979 dj.dir[DIR_Attr] = AM_VOL;
3980 tm = GET_FATTIME();
3981 ST_DWORD(dj.dir + DIR_CrtTime, tm);
3982 ST_DWORD(dj.dir + DIR_WrtTime, tm);
3983 dj.fs->wflag = 1;
3984 res = sync_fs(dj.fs);
3985 }
3986 }
3987 }
3988 }
3989 }
3990
3991 LEAVE_FF(dj.fs, res);
3992}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint vn
Definition: glfuncs.h:238

Referenced by main().

◆ f_stat()

FRESULT f_stat ( const TCHAR path,
FILINFO fno 
)

Definition at line 3369 of file ff.c.

3373{
3374 FRESULT res;
3375 DIR dj;
3377
3378
3379 /* Get logical drive number */
3380 res = find_volume(&dj.fs, &path, 0);
3381 if (res == FR_OK) {
3382 INIT_BUF(dj);
3383 res = follow_path(&dj, path); /* Follow the file path */
3384 if (res == FR_OK) { /* Follow completed */
3385 if (dj.dir) { /* Found an object */
3386 if (fno) get_fileinfo(&dj, fno);
3387 } else { /* It is root directory */
3389 }
3390 }
3391 FREE_BUF();
3392 }
3393
3394 LEAVE_FF(dj.fs, res);
3395}

◆ f_sync()

FRESULT f_sync ( FIL fp)

Definition at line 2809 of file ff.c.

2812{
2813 FRESULT res;
2814 DWORD tm;
2815 BYTE *dir;
2816
2817
2818 res = validate(fp); /* Check validity of the object */
2819 if (res == FR_OK) {
2820 if (fp->flag & FA__WRITTEN) { /* Is there any change to the file? */
2821#if !_FS_TINY
2822 if (fp->flag & FA__DIRTY) { /* Write-back cached data if needed */
2823 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
2824 LEAVE_FF(fp->fs, FR_DISK_ERR);
2825 fp->flag &= ~FA__DIRTY;
2826 }
2827#endif
2828 /* Update the directory entry */
2829 res = move_window(fp->fs, fp->dir_sect);
2830 if (res == FR_OK) {
2831 dir = fp->dir_ptr;
2832 dir[DIR_Attr] |= AM_ARC; /* Set archive bit */
2833 ST_DWORD(dir + DIR_FileSize, fp->fsize); /* Update file size */
2834 st_clust(dir, fp->sclust); /* Update start cluster */
2835 tm = GET_FATTIME(); /* Update modified time */
2838 fp->flag &= ~FA__WRITTEN;
2839 fp->fs->wflag = 1;
2840 res = sync_fs(fp->fs);
2841 }
2842 }
2843 }
2844
2845 LEAVE_FF(fp->fs, res);
2846}
#define DIR_LstAccDate
Definition: ff.c:415

Referenced by f_close().

◆ f_truncate()

FRESULT f_truncate ( FIL fp)

Definition at line 3470 of file ff.c.

3473{
3474 FRESULT res;
3475 DWORD ncl;
3476
3477
3478 res = validate(fp); /* Check validity of the object */
3479 if (res == FR_OK) {
3480 if (fp->err) { /* Check error */
3481 res = (FRESULT)fp->err;
3482 } else {
3483 if (!(fp->flag & FA_WRITE)) /* Check access mode */
3484 res = FR_DENIED;
3485 }
3486 }
3487 if (res == FR_OK) {
3488 if (fp->fsize > fp->fptr) {
3489 fp->fsize = fp->fptr; /* Set file size to current R/W point */
3490 fp->flag |= FA__WRITTEN;
3491 if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */
3492 res = remove_chain(fp->fs, fp->sclust);
3493 fp->sclust = 0;
3494 } else { /* When truncate a part of the file, remove remaining clusters */
3495 ncl = get_fat(fp->fs, fp->clust);
3496 res = FR_OK;
3497 if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR;
3498 if (ncl == 1) res = FR_INT_ERR;
3499 if (res == FR_OK && ncl < fp->fs->n_fatent) {
3500 res = put_fat(fp->fs, fp->clust, 0x0FFFFFFF);
3501 if (res == FR_OK) res = remove_chain(fp->fs, ncl);
3502 }
3503 }
3504#if !_FS_TINY
3505 if (res == FR_OK && (fp->flag & FA__DIRTY)) {
3506 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
3507 res = FR_DISK_ERR;
3508 else
3509 fp->flag &= ~FA__DIRTY;
3510 }
3511#endif
3512 }
3513 if (res != FR_OK) fp->err = (FRESULT)res;
3514 }
3515
3516 LEAVE_FF(fp->fs, res);
3517}

◆ f_unlink()

FRESULT f_unlink ( const TCHAR path)

Definition at line 3526 of file ff.c.

3529{
3530 FRESULT res;
3531 DIR dj, sdj;
3532 BYTE *dir;
3533 DWORD dclst = 0;
3535
3536
3537 /* Get logical drive number */
3538 res = find_volume(&dj.fs, &path, 1);
3539 if (res == FR_OK) {
3540 INIT_BUF(dj);
3541 res = follow_path(&dj, path); /* Follow the file path */
3542 if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
3543 res = FR_INVALID_NAME; /* Cannot remove dot entry */
3544#if _FS_LOCK
3545 if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open object */
3546#endif
3547 if (res == FR_OK) { /* The object is accessible */
3548 dir = dj.dir;
3549 if (!dir) {
3550 res = FR_INVALID_NAME; /* Cannot remove the origin directory */
3551 } else {
3552 if (dir[DIR_Attr] & AM_RDO)
3553 res = FR_DENIED; /* Cannot remove R/O object */
3554 }
3555 if (res == FR_OK) {
3556 dclst = ld_clust(dj.fs, dir);
3557 if (dclst && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-directory ? */
3558#if _FS_RPATH
3559 if (dclst == dj.fs->cdir) { /* Is it the current directory? */
3560 res = FR_DENIED;
3561 } else
3562#endif
3563 {
3564 mem_cpy(&sdj, &dj, sizeof (DIR)); /* Open the sub-directory */
3565 sdj.sclust = dclst;
3566 res = dir_sdi(&sdj, 2);
3567 if (res == FR_OK) {
3568 res = dir_read(&sdj, 0); /* Read an item (excluding dot entries) */
3569 if (res == FR_OK) res = FR_DENIED; /* Not empty? (cannot remove) */
3570 if (res == FR_NO_FILE) res = FR_OK; /* Empty? (can remove) */
3571 }
3572 }
3573 }
3574 }
3575 if (res == FR_OK) {
3576 res = dir_remove(&dj); /* Remove the directory entry */
3577 if (res == FR_OK && dclst) /* Remove the cluster chain if exist */
3578 res = remove_chain(dj.fs, dclst);
3579 if (res == FR_OK) res = sync_fs(dj.fs);
3580 }
3581 }
3582 FREE_BUF();
3583 }
3584
3585 LEAVE_FF(dj.fs, res);
3586}

Referenced by main().

◆ f_utime()

FRESULT f_utime ( const TCHAR path,
const FILINFO fno 
)

Definition at line 3791 of file ff.c.

3795{
3796 FRESULT res;
3797 DIR dj;
3798 BYTE *dir;
3800
3801
3802 /* Get logical drive number */
3803 res = find_volume(&dj.fs, &path, 1);
3804 if (res == FR_OK) {
3805 INIT_BUF(dj);
3806 res = follow_path(&dj, path); /* Follow the file path */
3807 FREE_BUF();
3808 if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT))
3810 if (res == FR_OK) {
3811 dir = dj.dir;
3812 if (!dir) { /* Root directory */
3814 } else { /* File or sub-directory */
3815 ST_WORD(dir + DIR_WrtTime, fno->ftime);
3816 ST_WORD(dir + DIR_WrtDate, fno->fdate);
3817 dj.fs->wflag = 1;
3818 res = sync_fs(dj.fs);
3819 }
3820 }
3821 }
3822
3823 LEAVE_FF(dj.fs, res);
3824}
#define DIR_WrtDate
Definition: ff.c:418
WORD fdate
Definition: ff.h:170
WORD ftime
Definition: ff.h:171

◆ f_write()

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

Definition at line 2687 of file ff.c.

2693{
2694 FRESULT res;
2695 DWORD clst, sect;
2696 UINT wcnt, cc;
2697 const BYTE *wbuff = (const BYTE*)buff;
2698 BYTE csect;
2699
2700
2701 *bw = 0; /* Clear write byte counter */
2702
2703 res = validate(fp); /* Check validity */
2704 if (res != FR_OK) LEAVE_FF(fp->fs, res);
2705 if (fp->err) /* Check error */
2706 LEAVE_FF(fp->fs, (FRESULT)fp->err);
2707 if (!(fp->flag & FA_WRITE)) /* Check access mode */
2708 LEAVE_FF(fp->fs, FR_DENIED);
2709 if (fp->fptr + btw < fp->fptr) btw = 0; /* File size cannot reach 4GB */
2710
2711 for ( ; btw; /* Repeat until all data written */
2712 wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) {
2713 if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */
2714 csect = (BYTE)(fp->fptr / SS(fp->fs) & (fp->fs->csize - 1)); /* Sector offset in the cluster */
2715 if (!csect) { /* On the cluster boundary? */
2716 if (fp->fptr == 0) { /* On the top of the file? */
2717 clst = fp->sclust; /* Follow from the origin */
2718 if (clst == 0) /* When no cluster is allocated, */
2719 clst = create_chain(fp->fs, 0); /* Create a new cluster chain */
2720 } else { /* Middle or end of the file */
2721#if _USE_FASTSEEK
2722 if (fp->cltbl)
2723 clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */
2724 else
2725#endif
2726 clst = create_chain(fp->fs, fp->clust); /* Follow or stretch cluster chain on the FAT */
2727 }
2728 if (clst == 0) break; /* Could not allocate a new cluster (disk full) */
2729 if (clst == 1) ABORT(fp->fs, FR_INT_ERR);
2730 if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR);
2731 fp->clust = clst; /* Update current cluster */
2732 if (fp->sclust == 0) fp->sclust = clst; /* Set start cluster if the first write */
2733 }
2734#if _FS_TINY
2735 if (fp->fs->winsect == fp->dsect && sync_window(fp->fs)) /* Write-back sector cache */
2736 ABORT(fp->fs, FR_DISK_ERR);
2737#else
2738 if (fp->flag & FA__DIRTY) { /* Write-back sector cache */
2739 if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
2740 ABORT(fp->fs, FR_DISK_ERR);
2741 fp->flag &= ~FA__DIRTY;
2742 }
2743#endif
2744 sect = clust2sect(fp->fs, fp->clust); /* Get current sector */
2745 if (!sect) ABORT(fp->fs, FR_INT_ERR);
2746 sect += csect;
2747 cc = btw / SS(fp->fs); /* When remaining bytes >= sector size, */
2748 if (cc) { /* Write maximum contiguous sectors directly */
2749 if (csect + cc > fp->fs->csize) /* Clip at cluster boundary */
2750 cc = fp->fs->csize - csect;
2751 if (disk_write(fp->fs->drv, wbuff, sect, cc) != RES_OK)
2752 ABORT(fp->fs, FR_DISK_ERR);
2753#if _FS_MINIMIZE <= 2
2754#if _FS_TINY
2755 if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
2756 mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs));
2757 fp->fs->wflag = 0;
2758 }
2759#else
2760 if (fp->dsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
2761 mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs));
2762 fp->flag &= ~FA__DIRTY;
2763 }
2764#endif
2765#endif
2766 wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */
2767 continue;
2768 }
2769#if _FS_TINY
2770 if (fp->fptr >= fp->fsize) { /* Avoid silly cache filling at growing edge */
2771 if (sync_window(fp->fs)) ABORT(fp->fs, FR_DISK_ERR);
2772 fp->fs->winsect = sect;
2773 }
2774#else
2775 if (fp->dsect != sect) { /* Fill sector cache with file data */
2776 if (fp->fptr < fp->fsize &&
2777 disk_read(fp->fs->drv, fp->buf, sect, 1) != RES_OK)
2778 ABORT(fp->fs, FR_DISK_ERR);
2779 }
2780#endif
2781 fp->dsect = sect;
2782 }
2783 wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
2784 if (wcnt > btw) wcnt = btw;
2785#if _FS_TINY
2786 if (move_window(fp->fs, fp->dsect) != FR_OK) /* Move sector window */
2787 ABORT(fp->fs, FR_DISK_ERR);
2788 mem_cpy(&fp->fs->win[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
2789 fp->fs->wflag = 1;
2790#else
2791 mem_cpy(&fp->buf[fp->fptr % SS(fp->fs)], wbuff, wcnt); /* Fit partial sector */
2792 fp->flag |= FA__DIRTY;
2793#endif
2794 }
2795
2796 if (fp->fptr > fp->fsize) fp->fsize = fp->fptr; /* Update file size if needed */
2797 fp->flag |= FA__WRITTEN; /* Set file change flag */
2798
2799 LEAVE_FF(fp->fs, FR_OK);
2800}
static int bw
Definition: maze.c:120

Referenced by main().

◆ find_volume()

static FRESULT find_volume ( FATFS **  rfs,
const TCHAR **  path,
BYTE  wmode 
)
static

Definition at line 2203 of file ff.c.

2208{
2209 BYTE fmt, *pt;
2210 int vol;
2211 DSTATUS stat;
2212 DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4];
2213 WORD nrsv;
2214 FATFS *fs;
2215 UINT i;
2216
2217
2218 /* Get logical drive number from the path name */
2219 *rfs = 0;
2220 vol = get_ldnumber(path);
2221 if (vol < 0) return FR_INVALID_DRIVE;
2222
2223 /* Check if the file system object is valid or not */
2224 fs = FatFs[vol]; /* Get pointer to the file system object */
2225 if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */
2226
2227 ENTER_FF(fs); /* Lock the volume */
2228 *rfs = fs; /* Return pointer to the file system object */
2229
2230 if (fs->fs_type) { /* If the volume has been mounted */
2231 stat = disk_status(fs->drv);
2232 if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
2233 if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */
2234 return FR_WRITE_PROTECTED;
2235 return FR_OK; /* The file system object is valid */
2236 }
2237 }
2238
2239 /* The file system object is not valid. */
2240 /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */
2241
2242 fs->fs_type = 0; /* Clear the file system object */
2243 fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */
2244 stat = disk_initialize(fs->drv); /* Initialize the physical drive */
2245 if (stat & STA_NOINIT) /* Check if the initialization succeeded */
2246 return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
2247 if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */
2248 return FR_WRITE_PROTECTED;
2249#if _MAX_SS != _MIN_SS /* Get sector size (multiple sector size cfg only) */
2250 if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK
2251 || SS(fs) < _MIN_SS || SS(fs) > _MAX_SS) return FR_DISK_ERR;
2252#endif
2253 /* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */
2254 bsect = 0;
2255 fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT boot sector as SFD */
2256 if (fmt == 1 || (!fmt && (LD2PT(vol)))) { /* Not an FAT boot sector or forced partition number */
2257 for (i = 0; i < 4; i++) { /* Get partition offset */
2258 pt = fs->win + MBR_Table + i * SZ_PTE;
2259 br[i] = pt[4] ? LD_DWORD(&pt[8]) : 0;
2260 }
2261 i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */
2262 if (i) i--;
2263 do { /* Find an FAT volume */
2264 bsect = br[i];
2265 fmt = bsect ? check_fs(fs, bsect) : 2; /* Check the partition */
2266 } while (!LD2PT(vol) && fmt && ++i < 4);
2267 }
2268 if (fmt == 3) return FR_DISK_ERR; /* An error occured in the disk I/O layer */
2269 if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */
2270
2271 /* An FAT volume is found. Following code initializes the file system object */
2272
2273 if (LD_WORD(fs->win + BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */
2274 return FR_NO_FILESYSTEM;
2275
2276 fasize = LD_WORD(fs->win + BPB_FATSz16); /* Number of sectors per FAT */
2277 if (!fasize) fasize = LD_DWORD(fs->win + BPB_FATSz32);
2278 fs->fsize = fasize;
2279
2280 fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FAT copies */
2281 if (fs->n_fats != 1 && fs->n_fats != 2) /* (Must be 1 or 2) */
2282 return FR_NO_FILESYSTEM;
2283 fasize *= fs->n_fats; /* Number of sectors for FAT area */
2284
2285 fs->csize = fs->win[BPB_SecPerClus]; /* Number of sectors per cluster */
2286 if (!fs->csize || (fs->csize & (fs->csize - 1))) /* (Must be power of 2) */
2287 return FR_NO_FILESYSTEM;
2288
2289 fs->n_rootdir = LD_WORD(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
2290 if (fs->n_rootdir % (SS(fs) / SZ_DIRE)) /* (Must be sector aligned) */
2291 return FR_NO_FILESYSTEM;
2292
2293 tsect = LD_WORD(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
2294 if (!tsect) tsect = LD_DWORD(fs->win + BPB_TotSec32);
2295
2296 nrsv = LD_WORD(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
2297 if (!nrsv) return FR_NO_FILESYSTEM; /* (Must not be 0) */
2298
2299 /* Determine the FAT sub type */
2300 sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZ_DIRE); /* RSV + FAT + DIR */
2301 if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
2302 nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
2303 if (!nclst) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
2304 fmt = FS_FAT12;
2305 if (nclst >= MIN_FAT16) fmt = FS_FAT16;
2306 if (nclst >= MIN_FAT32) fmt = FS_FAT32;
2307
2308 /* Boundaries and Limits */
2309 fs->n_fatent = nclst + 2; /* Number of FAT entries */
2310 fs->volbase = bsect; /* Volume start sector */
2311 fs->fatbase = bsect + nrsv; /* FAT start sector */
2312 fs->database = bsect + sysect; /* Data start sector */
2313 if (fmt == FS_FAT32) {
2314 if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
2315 fs->dirbase = LD_DWORD(fs->win + BPB_RootClus); /* Root directory start cluster */
2316 szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
2317 } else {
2318 if (!fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
2319 fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
2320 szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
2321 fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
2322 }
2323 if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) /* (BPB_FATSz must not be less than the size needed) */
2324 return FR_NO_FILESYSTEM;
2325
2326#if !_FS_READONLY
2327 /* Initialize cluster allocation information */
2328 fs->last_clust = fs->free_clust = 0xFFFFFFFF;
2329
2330 /* Get fsinfo if available */
2331 fs->fsi_flag = 0x80;
2332#if (_FS_NOFSINFO & 3) != 3
2333 if (fmt == FS_FAT32 /* Enable FSINFO only if FAT32 and BPB_FSInfo == 1 */
2334 && LD_WORD(fs->win + BPB_FSInfo) == 1
2335 && move_window(fs, bsect + 1) == FR_OK)
2336 {
2337 fs->fsi_flag = 0;
2338 if (LD_WORD(fs->win + BS_55AA) == 0xAA55 /* Load FSINFO data if available */
2339 && LD_DWORD(fs->win + FSI_LeadSig) == 0x41615252
2340 && LD_DWORD(fs->win + FSI_StrucSig) == 0x61417272)
2341 {
2342#if (_FS_NOFSINFO & 1) == 0
2343 fs->free_clust = LD_DWORD(fs->win + FSI_Free_Count);
2344#endif
2345#if (_FS_NOFSINFO & 2) == 0
2346 fs->last_clust = LD_DWORD(fs->win + FSI_Nxt_Free);
2347#endif
2348 }
2349 }
2350#endif
2351#endif
2352 fs->fs_type = fmt; /* FAT sub-type */
2353 fs->id = ++Fsid; /* File system mount ID */
2354#if _FS_RPATH
2355 fs->cdir = 0; /* Set current directory to root */
2356#endif
2357#if _FS_LOCK /* Clear file lock semaphores */
2358 clear_lock(fs);
2359#endif
2360
2361 return FR_OK;
2362}
DSTATUS disk_status(BYTE pdrv)
Definition: diskio.c:83
#define pt(x, y)
Definition: drawing.c:79
static WORD Fsid
Definition: ff.c:449
#define ENTER_FF(fs)
Definition: ff.c:42
static BYTE check_fs(FATFS *fs, DWORD sect)
Definition: ff.c:2175
@ FR_NO_FILESYSTEM
Definition: ff.h:198

Referenced by f_chmod(), f_getfree(), f_getlabel(), f_mkdir(), f_mount(), f_open(), f_opendir(), f_rename(), f_setlabel(), f_stat(), f_unlink(), and f_utime().

◆ fit_lfn()

static void fit_lfn ( const WCHAR lfnbuf,
BYTE dir,
BYTE  ord,
BYTE  sum 
)
static

Definition at line 1341 of file ff.c.

1347{
1348 UINT i, s;
1349 WCHAR wc;
1350
1351
1352 dir[LDIR_Chksum] = sum; /* Set checksum */
1353 dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */
1354 dir[LDIR_Type] = 0;
1356
1357 i = (ord - 1) * 13; /* Get offset in the LFN working buffer */
1358 s = wc = 0;
1359 do {
1360 if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective character */
1361 ST_WORD(dir+LfnOfs[s], wc); /* Put it */
1362 if (!wc) wc = 0xFFFF; /* Padding characters following last character */
1363 } while (++s < 13);
1364 if (wc == 0xFFFF || !lfnbuf[i]) ord |= LLEF; /* Bottom LFN part is the start of LFN sequence */
1365 dir[LDIR_Ord] = ord; /* Set the LFN order */
1366}
#define LDIR_Attr
Definition: ff.c:422
#define LDIR_Type
Definition: ff.c:423

Referenced by dir_register().

◆ follow_path()

static FRESULT follow_path ( DIR dp,
const TCHAR path 
)
static

Definition at line 2052 of file ff.c.

2056{
2057 FRESULT res;
2058 BYTE *dir, ns;
2059
2060
2061#if _FS_RPATH
2062 if (*path == '/' || *path == '\\') { /* There is a heading separator */
2063 path++; dp->sclust = 0; /* Strip it and start from the root directory */
2064 } else { /* No heading separator */
2065 dp->sclust = dp->fs->cdir; /* Start from the current directory */
2066 }
2067#else
2068 if (*path == '/' || *path == '\\') /* Strip heading separator if exist */
2069 path++;
2070 dp->sclust = 0; /* Always start from the root directory */
2071#endif
2072
2073 if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */
2074 res = dir_sdi(dp, 0);
2075 dp->dir = 0;
2076 } else { /* Follow path */
2077 for (;;) {
2078 res = create_name(dp, &path); /* Get a segment name of the path */
2079 if (res != FR_OK) break;
2080 res = dir_find(dp); /* Find an object with the sagment name */
2081 ns = dp->fn[NSFLAG];
2082 if (res != FR_OK) { /* Failed to find the object */
2083 if (res == FR_NO_FILE) { /* Object is not found */
2084 if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, */
2085 dp->sclust = 0; dp->dir = 0; /* it is the root directory and stay there */
2086 if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */
2087 res = FR_OK; /* Ended at the root directroy. Function completed. */
2088 } else { /* Could not find the object */
2089 if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */
2090 }
2091 }
2092 break;
2093 }
2094 if (ns & NS_LAST) break; /* Last segment matched. Function completed. */
2095 dir = dp->dir; /* Follow the sub-directory */
2096 if (!(dir[DIR_Attr] & AM_DIR)) { /* It is not a sub-directory and cannot follow */
2097 res = FR_NO_PATH; break;
2098 }
2099 dp->sclust = ld_clust(dp->fs, dir);
2100 }
2101 }
2102
2103 return res;
2104}
static FRESULT create_name(DIR *dp, const TCHAR **path)
Definition: ff.c:1843
Definition: mxnamespace.c:45

Referenced by f_chmod(), f_mkdir(), f_open(), f_opendir(), f_rename(), f_stat(), f_unlink(), and f_utime().

◆ gen_numname()

static void gen_numname ( BYTE dst,
const BYTE src,
const WCHAR lfn,
UINT  seq 
)
static

Definition at line 1379 of file ff.c.

1385{
1386 BYTE ns[8], c;
1387 UINT i, j;
1388 WCHAR wc;
1389 DWORD sr;
1390
1391
1392 mem_cpy(dst, src, 11);
1393
1394 if (seq > 5) { /* On many collisions, generate a hash number instead of sequential number */
1395 sr = seq;
1396 while (*lfn) { /* Create a CRC */
1397 wc = *lfn++;
1398 for (i = 0; i < 16; i++) {
1399 sr = (sr << 1) + (wc & 1);
1400 wc >>= 1;
1401 if (sr & 0x10000) sr ^= 0x11021;
1402 }
1403 }
1404 seq = (UINT)sr;
1405 }
1406
1407 /* itoa (hexdecimal) */
1408 i = 7;
1409 do {
1410 c = (seq % 16) + '0';
1411 if (c > '9') c += 7;
1412 ns[i--] = c;
1413 seq /= 16;
1414 } while (seq);
1415 ns[i] = '~';
1416
1417 /* Append the number */
1418 for (j = 0; j < i && dst[j] != ' '; j++) {
1419 if (IsDBCS1(dst[j])) {
1420 if (j == i - 1) break;
1421 j++;
1422 }
1423 }
1424 do {
1425 dst[j++] = (i < 8) ? ns[i++] : ' ';
1426 } while (j < 8);
1427}
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340

Referenced by dir_register().

◆ get_fat()

DWORD get_fat ( FATFS fs,
DWORD  clst 
)

Definition at line 818 of file ff.c.

822{
823 UINT wc, bc;
824 BYTE *p;
825 DWORD val;
826
827
828 if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */
829 val = 1; /* Internal error */
830
831 } else {
832 val = 0xFFFFFFFF; /* Default value falls on disk error */
833
834 switch (fs->fs_type) {
835 case FS_FAT12 :
836 bc = (UINT)clst; bc += bc / 2;
837 if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;
838 wc = fs->win[bc++ % SS(fs)];
839 if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break;
840 wc |= fs->win[bc % SS(fs)] << 8;
841 val = clst & 1 ? wc >> 4 : (wc & 0xFFF);
842 break;
843
844 case FS_FAT16 :
845 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break;
846 p = &fs->win[clst * 2 % SS(fs)];
847 val = LD_WORD(p);
848 break;
849
850 case FS_FAT32 :
851 if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
852 p = &fs->win[clst * 4 % SS(fs)];
853 val = LD_DWORD(p) & 0x0FFFFFFF;
854 break;
855
856 default:
857 val = 1; /* Internal error */
858 }
859 }
860
861 return val;
862}
PBATCH_CONTEXT bc
Definition: batch.c:67
GLuint GLfloat * val
Definition: glext.h:7180

Referenced by create_chain(), dir_next(), dir_sdi(), f_getfree(), f_lseek(), f_read(), f_truncate(), and remove_chain().

◆ get_fileinfo()

static void get_fileinfo ( DIR dp,
FILINFO fno 
)
static

Definition at line 1703 of file ff.c.

1707{
1708 UINT i;
1709 TCHAR *p, c;
1710 BYTE *dir;
1711#if _USE_LFN
1712 WCHAR w, *lfn;
1713#endif
1714
1715 p = fno->fname;
1716 if (dp->sect) { /* Get SFN */
1717 dir = dp->dir;
1718 i = 0;
1719 while (i < 11) { /* Copy name body and extension */
1720 c = (TCHAR)dir[i++];
1721 if (c == ' ') continue; /* Skip padding spaces */
1722 if (c == RDDEM) c = (TCHAR)DDEM; /* Restore replaced DDEM character */
1723 if (i == 9) *p++ = '.'; /* Insert a . if extension is exist */
1724#if _USE_LFN
1725 if (IsUpper(c) && (dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY)))
1726 c += 0x20; /* To lower */
1727#if _LFN_UNICODE
1728 if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dir[i]))
1729 c = c << 8 | dir[i++];
1730 c = ff_convert(c, 1); /* OEM -> Unicode */
1731 if (!c) c = '?';
1732#endif
1733#endif
1734 *p++ = c;
1735 }
1736 fno->fattrib = dir[DIR_Attr]; /* Attribute */
1737 fno->fsize = LD_DWORD(dir + DIR_FileSize); /* Size */
1738 fno->fdate = LD_WORD(dir + DIR_WrtDate); /* Date */
1739 fno->ftime = LD_WORD(dir + DIR_WrtTime); /* Time */
1740 }
1741 *p = 0; /* Terminate SFN string by a \0 */
1742
1743#if _USE_LFN
1744 if (fno->lfname) {
1745 i = 0; p = fno->lfname;
1746 if (dp->sect && fno->lfsize && dp->lfn_idx != 0xFFFF) { /* Get LFN if available */
1747 lfn = dp->lfn;
1748 while ((w = *lfn++) != 0) { /* Get an LFN character */
1749#if !_LFN_UNICODE
1750 w = ff_convert(w, 0); /* Unicode -> OEM */
1751 if (!w) { i = 0; break; } /* No LFN if it could not be converted */
1752 if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false on SBCS cfg) */
1753 p[i++] = (TCHAR)(w >> 8);
1754#endif
1755 if (i >= fno->lfsize - 1) { i = 0; break; } /* No LFN if buffer overflow */
1756 p[i++] = (TCHAR)w;
1757 }
1758 }
1759 p[i] = 0; /* Terminate LFN string by a \0 */
1760 }
1761#endif
1762}
UINT lfsize
Definition: ff.h:176
BYTE fattrib
Definition: ff.h:172
TCHAR fname[13]
Definition: ff.h:173
TCHAR * lfname
Definition: ff.h:175
DWORD fsize
Definition: ff.h:169

Referenced by f_readdir(), and f_stat().

◆ get_ldnumber()

static int get_ldnumber ( const TCHAR **  path)
static

Definition at line 2114 of file ff.c.

2117{
2118 const TCHAR *tp, *tt;
2119 UINT i;
2120 int vol = -1;
2121#if _STR_VOLUME_ID /* Find string drive id */
2122 static const char* const str[] = {_VOLUME_STRS};
2123 const char *sp;
2124 char c;
2125 TCHAR tc;
2126#endif
2127
2128
2129 if (*path) { /* If the pointer is not a null */
2130 for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find ':' in the path */
2131 if (*tt == ':') { /* If a ':' is exist in the path name */
2132 tp = *path;
2133 i = *tp++ - '0';
2134 if (i < 10 && tp == tt) { /* Is there a numeric drive id? */
2135 if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */
2136 vol = (int)i;
2137 *path = ++tt;
2138 }
2139 }
2140#if _STR_VOLUME_ID
2141 else { /* No numeric drive number, find string drive id */
2142 i = 0; tt++;
2143 do {
2144 sp = str[i]; tp = *path;
2145 do { /* Compare a string drive id with path name */
2146 c = *sp++; tc = *tp++;
2147 if (IsLower(tc)) tc -= 0x20;
2148 } while (c && (TCHAR)c == tc);
2149 } while ((c || tp != tt) && ++i < _VOLUMES); /* Repeat for each id until pattern match */
2150 if (i < _VOLUMES) { /* If a drive id is found, get the value and strip it */
2151 vol = (int)i;
2152 *path = tt;
2153 }
2154 }
2155#endif
2156 return vol;
2157 }
2158#if _FS_RPATH && _VOLUMES >= 2
2159 vol = CurrVol; /* Current drive */
2160#else
2161 vol = 0; /* Drive 0 */
2162#endif
2163 }
2164 return vol;
2165}
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
#define _VOLUMES
Definition: ffconf.h:141
#define _VOLUME_STRS
Definition: ffconf.h:146
#define _USE_LFN
Definition: ffconf.h:93
const GLfloat * tc
Definition: glext.h:8925
static const WCHAR sp[]
Definition: suminfo.c:287

Referenced by f_mkfs(), f_mount(), f_rename(), and find_volume().

◆ ld_clust()

static DWORD ld_clust ( FATFS fs,
const BYTE dir 
)
static

Definition at line 1235 of file ff.c.

1239{
1240 DWORD cl;
1241
1242 cl = LD_WORD(dir + DIR_FstClusLO);
1243 if (fs->fs_type == FS_FAT32)
1244 cl |= (DWORD)LD_WORD(dir + DIR_FstClusHI) << 16;
1245
1246 return cl;
1247}
#define DIR_FstClusHI
Definition: ff.c:416
#define DIR_FstClusLO
Definition: ff.c:419

Referenced by f_open(), f_opendir(), f_rename(), f_unlink(), and follow_path().

◆ mem_cmp()

static int mem_cmp ( const void dst,
const void src,
UINT  cnt 
)
static

Definition at line 533 of file ff.c.

533 {
534 const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
535 int r = 0;
536
537 while (cnt-- && (r = *d++ - *s++) == 0) ;
538 return r;
539}
GLdouble GLdouble GLdouble r
Definition: gl.h:2055

Referenced by dir_find().

◆ mem_cpy()

static void mem_cpy ( void dst,
const void src,
UINT  cnt 
)
static

Definition at line 507 of file ff.c.

507 {
508 BYTE *d = (BYTE*)dst;
509 const BYTE *s = (const BYTE*)src;
510
511#if _WORD_ACCESS == 1
512 while (cnt >= sizeof (int)) {
513 *(int*)d = *(int*)s;
514 d += sizeof (int); s += sizeof (int);
515 cnt -= sizeof (int);
516 }
517#endif
518 while (cnt--)
519 *d++ = *s++;
520}

Referenced by dir_register(), f_getlabel(), f_mkdir(), f_mkfs(), f_read(), f_rename(), f_setlabel(), f_unlink(), f_write(), and gen_numname().

◆ mem_set()

static void mem_set ( void dst,
int  val,
UINT  cnt 
)
static

Definition at line 524 of file ff.c.

524 {
525 BYTE *d = (BYTE*)dst;
526
527 while (cnt--)
528 *d++ = (BYTE)val;
529}

Referenced by create_name(), dir_next(), dir_register(), dir_remove(), f_mkdir(), f_mkfs(), f_setlabel(), and sync_fs().

◆ move_window()

static FRESULT move_window ( FATFS fs,
DWORD  sector 
)
static

Definition at line 729 of file ff.c.

733{
734 FRESULT res = FR_OK;
735
736
737 if (sector != fs->winsect) { /* Window offset changed? */
738#if !_FS_READONLY
739 res = sync_window(fs); /* Write-back changes */
740#endif
741 if (res == FR_OK) { /* Fill sector window with new data */
742 if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) {
743 sector = 0xFFFFFFFF; /* Invalidate window if data is not reliable */
745 }
746 fs->winsect = sector;
747 }
748 }
749 return res;
750}
uint32_t sector
Definition: isohybrid.c:61

Referenced by check_fs(), dir_alloc(), dir_find(), dir_read(), dir_register(), dir_remove(), f_getfree(), f_getlabel(), f_open(), f_read(), f_rename(), f_sync(), f_write(), find_volume(), get_fat(), and put_fat().

◆ pick_lfn()

static int pick_lfn ( WCHAR lfnbuf,
BYTE dir 
)
static

Definition at line 1307 of file ff.c.

1311{
1312 UINT i, s;
1313 WCHAR wc, uc;
1314
1315
1316 if (LD_WORD(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */
1317
1318 i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */
1319
1320 for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
1321 uc = LD_WORD(dir + LfnOfs[s]); /* Pick an LFN character */
1322 if (wc) {
1323 if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
1324 lfnbuf[i++] = wc = uc; /* Store it */
1325 } else {
1326 if (uc != 0xFFFF) return 0; /* Check filler */
1327 }
1328 }
1329
1330 if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */
1331 if (i >= _MAX_LFN) return 0; /* Buffer overflow? */
1332 lfnbuf[i] = 0;
1333 }
1334
1335 return 1; /* The part of LFN is valid */
1336}

Referenced by dir_read().

◆ put_fat()

FRESULT put_fat ( FATFS fs,
DWORD  clst,
DWORD  val 
)

Definition at line 873 of file ff.c.

878{
879 UINT bc;
880 BYTE *p;
881 FRESULT res;
882
883
884 if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */
885 res = FR_INT_ERR;
886
887 } else {
888 switch (fs->fs_type) {
889 case FS_FAT12 :
890 bc = (UINT)clst; bc += bc / 2;
891 res = move_window(fs, fs->fatbase + (bc / SS(fs)));
892 if (res != FR_OK) break;
893 p = &fs->win[bc++ % SS(fs)];
894 *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val