diff --git a/documents/00index_e.html b/documents/00index_e.html index 56c234d..ccb4186 100644 --- a/documents/00index_e.html +++ b/documents/00index_e.html @@ -17,7 +17,7 @@
layer -

FatFs is a generic FAT/exFAT filesystem module for small embedded systems. The FatFs module is written in compliance with ANSI C (C89) and completely separated from the disk control layer. Therefore it is independent of the platforms and storage devices. It can be incorporated into small microcontrollers with limited resource, such as 8051, PIC, AVR, ARM, Z80, RX and etc. Also Petit FatFs module for tiny microcontrollers is available here.

+

FatFs is a generic FAT/exFAT filesystem module for small embedded systems. The FatFs module is written in compliance with ANSI C (C89) and completely separated from the disk control layer. Therefore it is independent of the platforms and storage devices. It can be incorporated into small microcontrollers with limited resource, such as 8051, PIC, AVR, ARM, Z80, RX and etc. Also Petit FatFs module for tiny microcontrollers is available here🔗.

Features

diff --git a/documents/doc/appnote.html b/documents/doc/appnote.html index d86ec91..117645b 100644 --- a/documents/doc/appnote.html +++ b/documents/doc/appnote.html @@ -106,17 +106,17 @@ The FatFs module is a middleware written in ANSI C (C89). There is no platform d ARM7
32bit
ARM7
Thumb
CM3
Thumb-2
AVRH8/300HPIC24RL78V850ESSH-2ARX600IA-32 CompilerGCCGCCGCCGCCCH38C30CC78K0RCA850SHCRXCMSC -.text (Def, R/W)10.4k6.7k6.1k12.5k11.0k11.4k13.0k8.9k9.2k6.5k8.9k -.text (Min, R/W) 7.0k4.7k4.2k 8.5k 7.6k 7.9k 9.5k6.3k6.4k4.7k6.4k -.text (Def, R/O) 4.9k3.2k2.7k 6.1k 5.2k 5.4k 6.5k4.3k4.2k3.2k4.3k -.text (Min, R/O) 3.7k2.5k2.1k 4.4k 4.0k 4.2k 5.1k3.4k3.3k2.5k3.5k +.text (Def, R/W)10.5k6.7k6.1k12.6k11.0k11.4k13.0k8.9k9.2k6.5k8.9k +.text (Min, R/W) 7.0k4.7k4.2k 8.5k 7.6k 7.9k 9.4k6.3k6.4k4.7k6.3k +.text (Def, R/O) 4.9k3.2k2.8k 6.1k 5.2k 5.5k 6.5k4.4k4.2k3.2k4.3k +.text (Min, R/O) 3.7k2.5k2.1k 4.4k 4.0k 4.2k 5.0k3.4k3.3k2.5k3.4k .bssV*4 + 2V*4 + 2V*4 + 2V*2 + 2V*4 + 2V*2 + 2V*2 + 2V*4 + 2V*4 + 2V*4 + 2V*4 + 2 Work area
(FF_FS_TINY == 0)V*564
+ F*552V*564
+ F*552V*564
+ F*552V*560
+ F*546V*560
+ F*546V*560
+ F*546V*560
+ F*546V*564
+ F*552V*564
+ F*552V*564
+ F*552V*564
+ F*552 Work area
(FF_FS_TINY == 1)V*564
+ F*40V*564
+ F*40V*564
+ F*40V*560
+ F*34V*560
+ F*34V*560
+ F*34V*560
+ F*34V*564
+ F*40V*564
+ F*40V*564
+ F*40V*564
+ F*40

These are the memory usage of FatFs module without lower layer on some target systems in following condition. V denotes number of mounted volumes and F denotes number of open files. Every samples here are optimezed in code size.

-FatFs R0.15 options:
+FatFs R0.15b options:
 FF_FS_READONLY   0 (R/W, read/write) or 1 (R/O, read only)
 FF_FS_MINIMIZE   0 (Def, with all basic functions) or 3 (Min, with fully minimized)
 FF_FS_TINY       0 (Default) or 1 (Tiny file object)
@@ -202,7 +202,7 @@ And any other options are left unchanged from original setting.
 

64-bit LBA

LBA (Logical Block Addressing) is an addressing method to specify the location of data block, called sector, on the storage media. It is a simple linear address beginning from 0 as the first sector, 1 as the second sector and so on. The host system does not need to consider how the data block is located and managed in the storage device. FatFs supports only LBA for the media access. 32-bit LBA is a common size in the most LBA scheme. It can address up to 232 sectors, 2 TB in 512 bytes/sector. When a storage device larger than 2 TB is used, larger sector size or 64-bit LBA will be needed to address the entire sectors of the storage device.

-

By default, FatFs works in 32-bit LBA for media access. FatFs can also switch it to 64-bit LBA by a configuration option FF_LBA64. It also enables GPT (GUID Partition Table) for partiotion management on the storage device. For further information about GPT, refer to f_mkfs and f_fdisk function.

+

By default, FatFs works in 32-bit LBA for media access. FatFs can also switch it to 64-bit LBA by a configuration option FF_LBA64. It also enables GPT (GUID Partition Table) for partition management on the storage device. For further information about GPT, refer to f_mkfs and f_fdisk function.

diff --git a/documents/doc/chmod.html b/documents/doc/chmod.html index c70695b..569919c 100644 --- a/documents/doc/chmod.html +++ b/documents/doc/chmod.html @@ -25,7 +25,7 @@ FRESULT f_chmod (

Parameters

path
-
Pointer to the null-terminated string that specifies an object to be changed
+
Pointer to the null-terminated string that specifies an object to be changed. If a null pointer is given, the function fails with FR_INVALID_OBJECT.
attr
Attribute flags to be set in one or more combination of the following flags. The specified flags are set and others are cleard.
diff --git a/documents/doc/config.html b/documents/doc/config.html index a4a8905..af02568 100644 --- a/documents/doc/config.html +++ b/documents/doc/config.html @@ -56,6 +56,7 @@
  • FF_FS_EXFAT
  • FF_FS_NORTC
  • FF_NORTC_MON, FF_NORTC_MDAY, FF_NORTC_YEAR
  • +
  • FF_FS_CTIME
  • FF_FS_NOFSINFO
  • FF_FS_LOCK
  • FF_FS_REENTRANT
  • @@ -271,6 +272,9 @@ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb"};

    FF_NORTC_MON, FF_NORTC_MDAY, FF_NORTC_YEAR

    This set of options defines the time to be used in no RTC systems. This option has no effect in read-only configuration or FF_FS_NORTC == 0.

    +

    FF_FS_CTIME

    +

    This option enables (1) or disables (0) to access the file creation time with FILINFO structure.

    +

    FF_FS_NOFSINFO

    0 to 3. If you need to know correct free space on the FAT32 volume, set bit 0 of this option, and f_getfree function at first time after the volume mounted will force a full FAT scan. Bit 1 controls the use of last allocated cluster number for new allocation.

    diff --git a/documents/doc/dwrite.html b/documents/doc/dwrite.html index 15cd61f..39cdb63 100644 --- a/documents/doc/dwrite.html +++ b/documents/doc/dwrite.html @@ -58,7 +58,7 @@ DRESULT disk_write (

    Description

    The specified memory address is not that always aligned to word boundary because the argument is defined as BYTE*. For more information, refer to the description of disk_read function.

    Generally, a multiple sector write request (count > 1) must not be split into single sector transactions to the storage device, or the file write throughput will be drastically decreased.

    -

    FatFs expects delayed write function in the disk control layer. The write operation to the media does not need to be completed when return from this function by what write operation is in progress or data is only stored into the write-back cache. The write data on the buff is invalid after return from this function. The write completion request is done by CTRL_SYNC command of disk_ioctl function. Therefore, if a delayed write function is implemented, the write throughput of the filesystem will be improved.

    +

    FatFs expects the disk control layer may have a delayed write feature. The write operation to the media does not need to be completed when return from this function by what media write operation is in progress or data is stored into the write-back cache. The write data on the buff is invalid after return from this function. The write completion request is done by CTRL_SYNC command of disk_ioctl function. Therefore, if a delayed write feature is implemented, the write throughput of the filesystem will be improved.

    Remarks: Application program MUST NOT call this function, or FAT structure on the volume can be collapsed.

    diff --git a/documents/doc/findfirst.html b/documents/doc/findfirst.html index 7a446ed..e02ff03 100644 --- a/documents/doc/findfirst.html +++ b/documents/doc/findfirst.html @@ -67,10 +67,10 @@ FRESULT f_findfirst (
  • * - An any string in length of zero or longer.
  • ????* - An any string in length of four characters or longer.
  • -

    Since the matching algorithm uses recursion, number of wildcards in the matching pattern is limited to four to limit the stack usage. Any pattern with too many wildcards does not match any name. In LFN configuration, only fname[] is tested when FF_USE_FIND == 1 and also altname[] is tested when FF_USE_FIND == 2. There are some differences listed below between FatFs and standard systems in matching condition.

    +

    Since the matching algorithm uses recursion, number of wildcards in the matching pattern is limited to four to limit the stack usage. The pattern with too many wildcards does not match any name. In LFN configuration, only fname[] is tested when FF_USE_FIND == 1 and also altname[] is tested when FF_USE_FIND == 2. There are some differences listed below between FatFs and standard systems in matching condition.

    • "*.*" does not match any name without extension while it matches any name with or without extension in standard systems.
    • -
    • Any pattern terminated with a dot does not match any name while it matches the name without extensiton in standard systems.
    • +
    • The pattern terminated with a dot does not match any name while it matches the name without extensiton in standard systems.
    • DBCS extended characters are compared in case-sensitive when LFN is enabled with !FF_LFN_UNICODE.
    diff --git a/documents/doc/lseek.html b/documents/doc/lseek.html index 5a11b71..9016018 100644 --- a/documents/doc/lseek.html +++ b/documents/doc/lseek.html @@ -61,8 +61,8 @@ FRESULT f_rewind (
  • End of file. The specified ofs was clipped at end of the file in read-only mode.
  • Disk full. There is no free space on the volume to expand the file.
  • -

    The fast seek feature enables fast backward/long seek operations without FAT access by using an on-memory CLMT (cluster link map table). It is applied to f_read and f_write function as well, however, the file size cannot be expanded by f_write, f_lseek function while the file is at fast seek mode.

    -

    The fast seek mode is available when FF_USE_FASTSEEK = 1. The CLMT must be created into the DWORD array prior to use the fast seek mode. To create the CLMT, set address of the DWORD array to the member cltbl in the open file object, set the size of array in unit of items to the cltbl[0] and then call f_lseek function with ofs = CREATE_LINKMAP. After the function succeeded, no FAT access is occured in subsequent f_read, f_write, f_lseek function to the file. The number of items used or required is returned into the cltbl[0]. The number of items needed is (number of the file fragments + 1) * 2. For example, 12 items in the array will be used for the file fragmented in 5 portions. If the function failed with FR_NOT_ENOUGH_CORE, the size of given array is insufficient for the file.

    +

    The fast seek feature enables fast backward/long seek operations without FAT access by using an on-memory CLMT (cluster link map table). It is applied to f_read and f_write function as well, however, the file size cannot be expanded by f_write, f_lseek function while the file is in fast seek mode.

    +

    The fast seek mode is available when FF_USE_FASTSEEK = 1. The CLMT must be created into a DWORD array prior to use the fast seek mode. To create the CLMT, set address of the DWORD array to the member cltbl in the open file object, set the size of array in unit of items to the cltbl[0] and then call f_lseek function with ofs = CREATE_LINKMAP. The number of items used or required is returned into the cltbl[0]. The number of items needed is (number of the file fragments + 1) * 2. For example, 12 items in the array will be used for the file fragmented in 5 portions. If the function failed with FR_NOT_ENOUGH_CORE, the size of given array is insufficient for the file. After the function succeeded, no FAT access is occured in subsequent f_read, f_write, f_lseek function to the file. To disable the fast seek mode, set null pointer to the cltbl.

    diff --git a/documents/doc/mkfs.html b/documents/doc/mkfs.html index 7680d5f..030b91b 100644 --- a/documents/doc/mkfs.html +++ b/documents/doc/mkfs.html @@ -35,11 +35,11 @@ FRESULT f_mkfs (
    BYTE n_fat
    Specifies number of FAT copies on the FAT/FAT32 volume. Valid value for this member is 1 or 2. The default value (0) and any invaid value gives 1. If the FAT type is exFAT, this member has no effect.
    UINT align
    -
    Specifies alignment of the volume data area (file allocation pool, usually erase block boundary of flash memory media) in unit of sector. The valid value for this member is between 1 and 32768 inclusive in power of 2. If a zero (the default value) or any invalid value is given, the function obtains the block size from lower layer with disk_ioctl function.
    +
    Specifies alignment of the volume data area (file allocation pool, usually erase block boundary of flash memory media) in unit of sector. The valid value for this member is between 1 and 32768 inclusive in power of 2. If a zero (the default value) or an invalid value is given, the function obtains the block size from lower layer with disk_ioctl function.
    UINT n_root
    Specifies number of root directory entries on the FAT volume. Valid value for this member is up to 32768 and aligned to sector size / 32. The default value (0) and any invaid value gives 512. If the FAT type is FAT32 or exFAT, this member has no effect.
    DWORD au_size
    -
    Specifies size of the cluster (allocation unit) in unit of byte. The valid value for this member is between sector size and 128 * sector size inclusive in power of 2 for FAT/FAT32 volume and up to 16 MB in power of 2 for exFAT volume. If a zero (default value) or any invalid value is given, the function uses a default cluster size depends on the volume size.
    +
    Specifies size of the cluster (allocation unit) in unit of byte. The valid value for this member is between sector size and 128 * sector size inclusive in power of 2 for FAT/FAT32 volume and up to 16 MB in power of 2 for exFAT volume. If a zero (default value) or an invalid value is given, the function uses a default cluster size depends on the volume size.
    work
    Pointer to the working buffer used for the format process. If a null pointer is given with FF_USE_LFN == 3, the function uses a len bytes of heap memory in this function.
    @@ -68,8 +68,8 @@ FRESULT f_mkfs (

    The allocation unit, also known as cluster, is a unit of disk space allocation for files. When the size of allocation unit is 32768 bytes, a file with 100 bytes in size occupies 32768 bytes of disk space. The space efficiency of disk usage gets worse as increasing size of allocation unit, but, on the other hand, the read/write performance increases. Therefore the size of allocation unit is a trade-off between space efficiency and performance. For the large volumes in GB order, 32768 bytes or larger, automatically selected by default, is recommended for most case unless extremely many small files are created in the volume.

    When the logical drive to be formatted is associated with a physical drive (FF_MULTI_PARTITION == 0 or VolToPart[].pt == 0) and FM_SFD flag is not specified, a partition occupies entire drive space is created and then the FAT volume is created in the partition. When FM_SFD flag is specified, the FAT volume is created without any disk partitioning.

    When the logical drive to be formatted is associated with a specific partition by multiple partition feature (FF_MULTI_PARTITION == 1 and VolToPart[].pt > 0), the FAT volume is created in the partition of the physical drive specified by volume mapping table and FM_SFD flag is ignored. The hosting physical drive needs to be partitioned with f_fdisk function or some partitioning tool prior to create the FAT volume with this function. If the partition is not exist, the function fails with FR_MKFS_ABORTED.

    -

    There are three standard disk partitioning formats, MBR, GPT and SFD. The MBR format, also known as FDISK format, is usually used for harddisk, memory card and U disk. It can divide a physical drive into one or more partitions with a partition table. The GPT, GUID Partition Table, is a newly defined patitioning format for large storage devices. FatFs suppors the GPT only when 64-bit LBA is enabled. The SFD, Super-Floppy Disk, is non-partitioned disk format. The FAT volume is located at LBA 0 and occupies the entire physical drive without any disk partitioning. It is usually used for floppy disk, optical disk and most super-floppy media. Some combination of systems and media support only either partitioned format or non-partitioned format and the other is not supported.

    -

    Some systems manage the partitions in the on-board storage in non-standard format. The partitions are mapped as physical drives identified by pdrv in disk_* functions. For such systems, SFD format is suitable to create the FAT volume in the partition.

    +

    There are three standard disk partitioning formats, MBR, GPT and SFD. The MBR format, also known as FDISK format, is usually used for harddisk, memory card and U disk. It can divide a physical drive into one or more partitions with a partition table. The GPT, GUID Partition Table, is a newly defined patitioning format for large storage devices. FatFs suppors the GPT only when 64-bit LBA is enabled. The SFD, Super-Floppy Disk, is non-partitioned disk format. The FAT volume is located at LBA 0 and occupies the entire physical drive without disk partitioning. It is usually used for floppy disk, optical disk and most super-floppy media. Some combination of systems and media support only either partitioned format or non-partitioned format and the other is not supported.

    +

    Some systems manage the partitions of on-board storage in non-standard format. The partitions are mapped as physical drives identified by pdrv in disk_* functions. For such systems, SFD format is suitable to create the FAT volume in the partition.

    diff --git a/documents/doc/readdir.html b/documents/doc/readdir.html index 5550cee..7feb32d 100644 --- a/documents/doc/readdir.html +++ b/documents/doc/readdir.html @@ -86,16 +86,16 @@ FRESULT list_dir (const char *path) int nfile, ndir; - res = f_opendir(&dir, path); /* Open the directory */ + res = f_opendir(&dir, path); /* Open the directory */ if (res == FR_OK) { nfile = ndir = 0; for (;;) { - res = f_readdir(&dir, &fno); /* Read a directory item */ - if (res != FR_OK || fno.fname[0] == 0) break; /* Error or end of dir */ - if (fno.fattrib & AM_DIR) { /* Directory */ + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (fno.fname[0] == 0) break; /* Error or end of dir */ + if (fno.fattrib & AM_DIR) { /* It is a directory */ printf(" <DIR> %s\n", fno.fname); ndir++; - } else { /* File */ + } else { /* It is a file */ printf("%10u %s\n", fno.fsize, fno.fname); nfile++; } @@ -121,18 +121,18 @@ FRESULT scan_files ( static FILINFO fno; - res = f_opendir(&dir, path); /* Open the directory */ + res = f_opendir(&dir, path); /* Open the directory */ if (res == FR_OK) { for (;;) { - res = f_readdir(&dir, &fno); /* Read a directory item */ - if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */ - if (fno.fattrib & AM_DIR) { /* It is a directory */ + res = f_readdir(&dir, &fno); /* Read a directory item */ + if (fno.fname[0] == 0) break; /* Break on error or end of dir */ + if (fno.fattrib & AM_DIR) { /* The item is a directory */ i = strlen(path); sprintf(&path[i], "/%s", fno.fname); - res = scan_files(path); /* Enter the directory */ + res = scan_files(path); /* Enter the directory */ if (res != FR_OK) break; path[i] = 0; - } else { /* It is a file. */ + } else { /* The item is a file. */ printf("%s/%s\n", path, fno.fname); } } diff --git a/documents/doc/setlabel.html b/documents/doc/setlabel.html index 8812d53..64e7908 100644 --- a/documents/doc/setlabel.html +++ b/documents/doc/setlabel.html @@ -55,7 +55,7 @@ FRESULT f_setlabel (
  • Allowable characters for exFAT volume are: characters allowed for LFN includes dot. Low-case characters are preserved.
  • Spaces can be embedded anywhere in the volume label. Trailing spaces are truncated off at FAT volume.
  • -

    Remark: The standard system (Windows) has a problem at the volume label with a heading \xE5 on the FAT volume. To avoid this problem, this function rejects such volume label as invalid name.

    +

    Remark: The standard system (Windows) has a problem in the volume label with a heading \xE5 on the FAT volume. To avoid this problem, this function rejects such volume label as invalid name.

    diff --git a/documents/doc/sfileinfo.html b/documents/doc/sfileinfo.html index 0e0ba91..e1fe1d2 100644 --- a/documents/doc/sfileinfo.html +++ b/documents/doc/sfileinfo.html @@ -17,6 +17,10 @@ FSIZE_t fsize; /* File size */ WORD fdate; /* Last modified date */ WORD ftime; /* Last modified time */ +#if FF_FS_CRTIME + WORD crdate; /* Created date */ + WORD crtime; /* Created time */ +#endif BYTE fattrib; /* Attribute */ #if FF_USE_LFN TCHAR altname[FF_SFN_BUF + 1]; /* Alternative object name */ @@ -54,6 +58,12 @@
    Second / 2 (0..29)
    +
    crdate
    +
    The date when the file/directory was created. This member is available when FF_FS_CRTIME = 1. +
    +
    crtime
    +
    The time when the file/directory was created. This member is available when FF_FS_CRTIME = 1 +
    fattrib
    The attribute flags in combination of:
    @@ -66,7 +76,7 @@
    fname[]
    -
    Null-terminated object name. A null string is stored when no item to read and it indicates this structure is invalid. The size of fname[] and altname[] each can be configured in LFN configuration.
    +
    Null-terminated object name is stored. If no item to read or an error occured in the function, a null string is stored to indicate this structure is invalid. The size of fname[] and altname[] each can be configured in LFN configuration.
    altname[]
    Alternative object name is stored if available. This member is not available in non-LFN configuration.
    diff --git a/documents/doc/stat.html b/documents/doc/stat.html index f8c10a1..66806e0 100644 --- a/documents/doc/stat.html +++ b/documents/doc/stat.html @@ -102,7 +102,7 @@ FRESULT f_stat (
    -

    References

    +

    See Also

    f_opendir, f_readdir, FILINFO

    diff --git a/documents/doc/utime.html b/documents/doc/utime.html index 6f94e8c..9f07321 100644 --- a/documents/doc/utime.html +++ b/documents/doc/utime.html @@ -15,7 +15,7 @@
     FRESULT f_utime (
       const TCHAR* path,  /* [IN] Object name */
    -  const FILINFO* fno  /* [IN] Time and data to be set */
    +  const FILINFO* fno  /* [IN] Time and date to be set */
     );
     
    @@ -26,7 +26,7 @@ FRESULT f_utime (
    path
    Pointer to the null-terminated string that specifies an object to be changed. If a null pointer is given, the function fails with FR_INVALID_DRIVE.
    fno
    -
    Pointer to the file information structure that has a timestamp to be set in member fdate and ftime. Do not care any other members.
    +
    Pointer to the file information structure that has new timestamps to be set in the members. fdate and ftime are for the last modified time. When FF_FS_CRTIME = 1, crdate and crtime for the created time are available in addition. Every timestamp is in local time. If fdate or crdate is invalid (0), the modified time or created time is left unchanged respectively. Do not care any other member.
    @@ -61,7 +61,7 @@ FRESULT f_utime (

    Example

     FRESULT set_timestamp (
    -    char *obj,     /* Pointer to the file name */
    +    const char *fname,     /* Pointer to the file name */
         int year,
         int month,
         int mday,
    @@ -74,8 +74,10 @@ FRESULT set_timestamp (
     
         fno.fdate = (WORD)(((year - 1980) * 512U) | month * 32U | mday);
         fno.ftime = (WORD)(hour * 2048U | min * 32U | sec / 2U);
    -
    -    return f_utime(obj, &fno);
    +#if FF_FS_CRTIME
    +    fno.crdate = 0;   /* Do not change created time in this code */
    +#endif
    +    return f_utime(fname, &fno);
     }
     
    diff --git a/documents/updates.html b/documents/updates.html index 9db87b7..facbdc4 100644 --- a/documents/updates.html +++ b/documents/updates.html @@ -4,14 +4,38 @@ - FatFs - Updates and Migration Notes

    Updates and Migration Notes

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    RevisionUpdatesMigration Notes
    R0.15b
    Jun 21, 2025
    +Added support for timestamp of created time. (FF_FS_CRTIME)
    +Fixed FatFs fails to load the FsInfo in FAT32 volumes and the f_getfree always be forced a full FAT scan which takes a long time. (appeared at R0.15a)
    +
    +Small changes to the f_utime function to support for the timestamp of created time.
    +
    R0.15a
    Nov 22, 2024
    +Fixed a complie error when FF_FS_LOCK != 0. (appeared at R0.15)
    +Fixed a potential issue when work FatFs concurrency with FF_FS_REENTRANT, FF_VOLUMES >= 2 and FF_FS_LOCK > 0.
    +Made f_setlabel accept a volume label with Unix style volume ID when FF_STR_VOLUME_ID == 2.
    +Made FatFs update PercInUse field in exFAT VBR. (A preceding f_getfree is needed for the accuracy)
    +
    +
    R0.15
    Nov 6, 2022
    @@ -27,6 +51,7 @@ User provided synchronization functions, ff_cre_syncobj, ff_del_syn FF_SYNC_t is removed from the configuration options.
    R0.14b
    Apr 17, 2021
    @@ -43,6 +68,7 @@ Fixed some compiler warnings.
    From this revision, FatFs depends on string.h.
    R0.14a
    Dec 05, 2020
    @@ -54,6 +80,7 @@ Fixed some compiler warnings.
    Number of wildcards in the matching pattern in f_findfirst is limited to 4.
    R0.14
    Oct 14, 2019
    @@ -68,6 +95,7 @@ Fixed f_mkfs can fail to create exFAT volume in the second partition. ( Usage of f_mkfs and f_fdisk is changed and some features are added to these functions.
    R0.13c
    Oct 14, 2018
    @@ -81,6 +109,7 @@ From this revision, FatFs depends on stdint.h in C99 or later.
    integer.h is removed.
    R0.13b
    Apr 07, 2018
    @@ -92,6 +121,7 @@ Fixed f_setlabel does not reject some invalid characters. (appeared at
    R0.13a
    Oct 14, 2017
    @@ -105,6 +135,7 @@ Fixed f_setlabel rejects some valid characters for exFAT volume. (appea
    R0.13
    May 21, 2017
    @@ -121,6 +152,7 @@ Fixed creating a file can fail when a new cluster allocation to the exFAT direct ASCII only configuration, FF_CODE_PAGE = 1, is removed. Use FF_CODE_PAGE = 437 instead.
    R0.12c
    Mar 04, 2017
    @@ -132,6 +164,7 @@ Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.1
    R0.12b
    Sep 4, 2016
    @@ -147,6 +180,7 @@ Fixed some internal errors in f_expand and f_lseek. (appeared
    R0.12a
    Jul 10, 2016
    @@ -161,6 +195,7 @@ Fixed compilation fails at some configurations, _USE_FASTSEEK and _ Usage of f_mkfs is changed.
    R0.12
    Apr 12, 2016
    @@ -180,6 +215,7 @@ To use f_chmod, _USE_CHMOD needs to be set.
    _WORD_ACCESS is removed from the configuration options.
    R0.11a
    Sep 5, 2015
    @@ -192,6 +228,7 @@ Fixed errors in the case conversion teble of Unicode (cc*.c).
    Removed some code pages actually not exist on the standard systems. (_CODE_PAGE)
    R0.11
    Feb 9, 2015
    @@ -202,6 +239,7 @@ Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
    R0.10c
    Nov 9, 2014
    @@ -213,6 +251,7 @@ Fixed null pointer dereference on attempting to delete the root direcotry. (appe
    R0.10b
    May 19, 2014
    @@ -222,6 +261,7 @@ Fixed LFN entry is not deleted on delete/rename an object with its lossy convert
    R0.10a
    Jan 15, 2014
    @@ -236,6 +276,7 @@ Fixed creation of a directory entry with LFN fails on too many SFN collisions. (
    R0.10
    Oct 2, 2013
    @@ -252,6 +293,7 @@ Fixed f_open, f_mkdir and f_setlabel can return incor
    R0.09b
    Jan 24, 2013
    @@ -260,6 +302,7 @@ Added f_getlabel and f_setlabel. (_USE_LABEL)
    R0.09a
    Aug 27, 2012
    @@ -270,6 +313,7 @@ Changed option name _FS_SHARE to _FS_LOCK.
    R0.09
    Sep 6, 2011
    @@ -279,6 +323,7 @@ Added f_fdisk. (_MULTI_PARTITION = 2)
    R0.08b
    Jan 15, 2011
    @@ -290,6 +335,7 @@ Ignores duplicated directory separators in given path names.
    R0.08a
    Aug 16, 2010
    @@ -302,6 +348,7 @@ Fixed f_mkfs creates wrong FAT32 volume.
    R0.08
    May 15, 2010
    @@ -315,6 +362,7 @@ String functions support UTF-8 encoding files on Unicode cfg.
    R0.07e
    Nov 3, 2009
    @@ -327,6 +375,7 @@ Changed f_readdir to return the SFN with always upper case on non-LFN c
    R0.07c
    Jan 21, 2009
    @@ -340,6 +389,7 @@ Added proper case conversion to extended characters.
    R0.07a
    Apr 14, 2009
    @@ -349,6 +399,7 @@ Added multiple sector size support.
    R0.07
    Apr 1, 2009
    @@ -364,6 +415,7 @@ Renamed string functions to avoid name collision.
    R0.06
    Apr 1, 2008
    @@ -374,6 +426,7 @@ Improved performance of f_lseek on moving to the same or following clus
    R0.05a
    Feb 3, 2008
    @@ -386,6 +439,7 @@ Fixed cached sector is left not flushed when create and close without write.
    R0.05
    Aug 26, 2007
    @@ -397,6 +451,7 @@ Fixed f_mkdir on FAT32 creates broken directory. (FatFs)
    R0.04b
    May 5, 2007
    @@ -409,6 +464,7 @@ Fixed short seek (<= csize) collapses the file object.
    R0.04a
    Apr 1, 2007
    @@ -421,6 +477,7 @@ Fixed a problem corresponds to FAT32 support. (Tiny-FatFs)
    R0.04
    Feb 4, 2007
    @@ -432,6 +489,7 @@ Added _USE_FAT32 option. (Tiny-FatFs)
    R0.03a
    Dec 11, 2006
    @@ -441,6 +499,7 @@ Fixed f_mkdir creates broken directory on FAT32.
    R0.03
    Sep 22, 2006
    @@ -450,6 +509,7 @@ Changed option _FS_MINIMUM to _FS_MINIMIZE.
    R0.02a
    Jun 10, 2006
    @@ -458,6 +518,7 @@ Added a configuration option _FS_MINIMUM.
    R0.02
    Jun 01, 2006
    @@ -468,6 +529,7 @@ Fixed a problem on small (<32M) patition.
    R0.01
    Apr 29, 2006
    @@ -477,5 +539,6 @@ First release.
    +

    Return

    diff --git a/source/00history.txt b/source/00history.txt index f154833..53487b3 100644 --- a/source/00history.txt +++ b/source/00history.txt @@ -375,3 +375,9 @@ R0.15a (November 22, 2024) Made f_setlabel() accept a volume label in Unix style volume ID when FF_STR_VOLUME_ID == 2. Made FatFs update PercInUse field in exFAT VBR. (A preceding f_getfree() is needed for the accuracy) + + +R0.15b (June 21, 2025) + Added support for timestamp of created time. (FF_FS_CRTIME) + Fixed FatFs fails to load the FsInfo in FAT32 volumes and the f_getfree always be forced a full FAT scan which takes a long time. (appeared at R0.15a) + diff --git a/source/ff.c b/source/ff.c index dcdae31..aad124a 100644 --- a/source/ff.c +++ b/source/ff.c @@ -1,8 +1,8 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem Module R0.15a / +/ FatFs - Generic FAT Filesystem Module R0.15b / /-----------------------------------------------------------------------------/ / -/ Copyright (C) 2024, ChaN, all right reserved. +/ Copyright (C) 2025, ChaN, all right reserved. / / FatFs module is an open source software. Redistribution and use of FatFs in / source and binary forms, with or without modification, are permitted provided @@ -30,7 +30,7 @@ ---------------------------------------------------------------------------*/ -#if FF_DEFINED != 5380 /* Revision ID */ +#if FF_DEFINED != 5385 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -194,7 +194,7 @@ #define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ #define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ #define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ -#define FSI_TrailSig 498 /* FAT32 FSI: Trailing signature (DWORD) */ +#define FSI_TrailSig 508 /* FAT32 FSI: Trailing signature (DWORD) */ #define MBR_Table 446 /* MBR: Offset of partition table in the MBR */ #define SZ_PTE 16 /* MBR: Size of a partition table entry */ @@ -222,7 +222,7 @@ #define GPTH_PtNum 80 /* GPT HDR: Number of table entries (DWORD) */ #define GPTH_PteSize 84 /* GPT HDR: Size of table entry (DWORD) */ #define GPTH_PtBcc 88 /* GPT HDR: Partition table BCC (DWORD) */ -#define SZ_GPTE 128 /* GPT PTE: Size of partition table entry */ +#define SZ_GPTE 128 /* GPT PTE: Size of a GPT partition table entry */ #define GPTE_PtGuid 0 /* GPT PTE: Partition type GUID (16-byte) */ #define GPTE_UpGuid 16 /* GPT PTE: Partition unique GUID (16-byte) */ #define GPTE_FstLba 32 /* GPT PTE: First LBA of partition (QWORD) */ @@ -617,7 +617,7 @@ static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); /* Load/Store multi-byte word in the FAT structure */ /*-----------------------------------------------------------------------*/ -static WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ +static WORD ld_16 (const BYTE* ptr) /* Load a 2-byte little-endian word */ { WORD rv; @@ -626,7 +626,7 @@ static WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ return rv; } -static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ +static DWORD ld_32 (const BYTE* ptr) /* Load a 4-byte little-endian word */ { DWORD rv; @@ -638,7 +638,7 @@ static DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ } #if FF_FS_EXFAT -static QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ +static QWORD ld_64 (const BYTE* ptr) /* Load an 8-byte little-endian word */ { QWORD rv; @@ -655,13 +655,13 @@ static QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ #endif #if !FF_FS_READONLY -static void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ +static void st_16 (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; } -static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ +static void st_32 (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; @@ -670,7 +670,7 @@ static void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-end } #if FF_FS_EXFAT -static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ +static void st_64 (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; @@ -1122,11 +1122,11 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ if (fs->fs_type == FS_FAT32) { /* FAT32: Update FSInfo sector */ /* Create FSInfo structure */ memset(fs->win, 0, sizeof fs->win); - st_dword(fs->win + FSI_LeadSig, 0x41615252); /* Leading signature */ - st_dword(fs->win + FSI_StrucSig, 0x61417272); /* Structure signature */ - st_dword(fs->win + FSI_Free_Count, fs->free_clst); /* Number of free clusters */ - st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); /* Last allocated culuster */ - st_dword(fs->win + FSI_TrailSig, 0xAA550000); /* Trailing signature */ + st_32(fs->win + FSI_LeadSig, 0x41615252); /* Leading signature */ + st_32(fs->win + FSI_StrucSig, 0x61417272); /* Structure signature */ + st_32(fs->win + FSI_Free_Count, fs->free_clst); /* Number of free clusters */ + st_32(fs->win + FSI_Nxt_Free, fs->last_clst); /* Last allocated culuster */ + st_32(fs->win + FSI_TrailSig, 0xAA550000); /* Trailing signature */ disk_write(fs->pdrv, fs->win, fs->winsect = fs->volbase + 1, 1); /* Write it into the FSInfo sector (Next to VBR) */ } #if FF_FS_EXFAT @@ -1202,12 +1202,12 @@ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFF case FS_FAT16 : if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; - val = ld_word(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */ + val = ld_16(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */ break; case FS_FAT32 : if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; - val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */ + val = ld_32(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */ break; #if FF_FS_EXFAT case FS_EXFAT : @@ -1228,7 +1228,7 @@ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFF val = 0x7FFFFFFF; /* Generate EOC */ } else { if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; - val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; + val = ld_32(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; } break; } @@ -1282,7 +1282,7 @@ static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ case FS_FAT16: res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); if (res != FR_OK) break; - st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */ + st_16(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */ fs->wflag = 1; break; @@ -1293,9 +1293,9 @@ static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); if (res != FR_OK) break; if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { - val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); + val = (val & 0x0FFFFFFF) | (ld_32(fs->win + clst * 4 % SS(fs)) & 0xF0000000); } - st_dword(fs->win + clst * 4 % SS(fs), val); + st_32(fs->win + clst * 4 % SS(fs), val); fs->wflag = 1; break; } @@ -1870,9 +1870,9 @@ static DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ { DWORD cl; - cl = ld_word(dir + DIR_FstClusLO); + cl = ld_16(dir + DIR_FstClusLO); if (fs->fs_type == FS_FAT32) { - cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16; + cl |= (DWORD)ld_16(dir + DIR_FstClusHI) << 16; } return cl; @@ -1886,9 +1886,9 @@ static void st_clust ( DWORD cl /* Value to be set */ ) { - st_word(dir + DIR_FstClusLO, (WORD)cl); + st_16(dir + DIR_FstClusLO, (WORD)cl); if (fs->fs_type == FS_FAT32) { - st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16)); + st_16(dir + DIR_FstClusHI, (WORD)(cl >> 16)); } } #endif @@ -1909,12 +1909,12 @@ static int cmp_lfn ( /* 1:matched, 0:not matched */ WCHAR pchr, chr; - if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check if LDIR_FstClusLO is 0 */ + if (ld_16(dir + LDIR_FstClusLO) != 0) return 0; /* Check if LDIR_FstClusLO is 0 */ ni = (UINT)((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the name to be compared */ for (pchr = 1, di = 0; di < 13; di++) { /* Process all characters in the entry */ - chr = ld_word(dir + LfnOfs[di]); /* Pick a character from the entry */ + chr = ld_16(dir + LfnOfs[di]); /* Pick a character from the entry */ if (pchr != 0) { if (ni >= FF_MAX_LFN + 1 || ff_wtoupper(chr) != ff_wtoupper(lfnbuf[ni++])) { /* Compare it with name */ return 0; /* Not matched */ @@ -1945,12 +1945,12 @@ static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ WCHAR pchr, chr; - if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check if LDIR_FstClusLO is 0 */ + if (ld_16(dir + LDIR_FstClusLO) != 0) return 0; /* Check if LDIR_FstClusLO is 0 */ ni = (UINT)((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Offset in the name buffer */ for (pchr = 1, di = 0; di < 13; di++) { /* Process all characters in the entry */ - chr = ld_word(dir + LfnOfs[di]); /* Pick a character from the entry */ + chr = ld_16(dir + LfnOfs[di]); /* Pick a character from the entry */ if (pchr != 0) { if (ni >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */ lfnbuf[ni++] = pchr = chr; /* Store it */ @@ -1988,13 +1988,13 @@ static void put_lfn ( dir[LDIR_Chksum] = sum; /* Set checksum */ dir[LDIR_Attr] = AM_LFN; /* Set attribute */ dir[LDIR_Type] = 0; - st_word(dir + LDIR_FstClusLO, 0); + st_16(dir + LDIR_FstClusLO, 0); ni = (UINT)(ord - 1) * 13; /* Offset in the name */ di = chr = 0; do { /* Fill the directory entry */ if (chr != 0xFFFF) chr = lfn[ni++]; /* Get an effective character */ - st_word(dir + LfnOfs[di], chr); /* Set it */ + st_16(dir + LfnOfs[di], chr); /* Set it */ if (chr == 0) chr = 0xFFFF; /* Padding characters after the terminator */ } while (++di < 13); if (chr == 0xFFFF || !lfn[ni]) ord |= LLEF; /* Last LFN part is the start of an enrty set */ @@ -2015,7 +2015,7 @@ static void gen_numname ( BYTE* dst, /* Pointer to the buffer to store numbered SFN */ const BYTE* src, /* Pointer to SFN in directory form */ const WCHAR* lfn, /* Pointer to LFN */ - UINT seq /* Sequence number */ + WORD seq /* Sequence number */ ) { BYTE ns[8], c; @@ -2036,10 +2036,10 @@ static void gen_numname ( if (crc_sreg & 0x10000) crc_sreg ^= 0x11021; } } - seq = (UINT)crc_sreg; + seq = (WORD)crc_sreg; } - /* Make suffix (~ + hexdecimal) */ + /* Make suffix (~ + 4-digit hexadecimal) */ i = 7; do { c = (BYTE)((seq % 16) + '0'); seq /= 16; @@ -2186,7 +2186,7 @@ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ /* Sanity check (do it for only accessible object) */ if (i <= MAXDIRB(FF_MAX_LFN)) { - if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR; + if (xdir_sum(dirb) != ld_16(dirb + XDIR_SetSum)) return FR_INT_ERR; } return FR_OK; @@ -2202,10 +2202,10 @@ static void init_alloc_info ( FFOBJID* obj /* Object allocation information to be initialized */ ) { - obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Start cluster */ - obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */ - obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; /* Allocation status */ - obj->n_frag = 0; /* No last fragment info */ + obj->sclust = ld_32(fs->dirbuf + XDIR_FstClus); /* Start cluster */ + obj->objsize = ld_64(fs->dirbuf + XDIR_FileSize); /* Size */ + obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; /* Allocation status */ + obj->n_frag = 0; /* No last fragment info */ } @@ -2253,7 +2253,7 @@ static FRESULT store_xdir ( BYTE *dirb = dp->obj.fs->dirbuf; /* Pointer to the entry set 85+C0+C1s */ - st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); /* Create check sum */ + st_16(dirb + XDIR_SetSum, xdir_sum(dirb)); /* Create check sum */ /* Store the entry set to the directory */ nent = dirb[XDIR_NumSec] + 1; /* Number of entries */ @@ -2300,7 +2300,7 @@ static void create_xdir ( dirb[i++] = ET_FILENAME; dirb[i++] = 0; do { /* Fill name field */ if (chr != 0 && (chr = lfn[nlen]) != 0) nlen++; /* Get a character if exist */ - st_word(dirb + i, chr); /* Store it */ + st_16(dirb + i, chr); /* Store it */ i += 2; } while (i % SZDIRE != 0); n_c1++; @@ -2308,7 +2308,7 @@ static void create_xdir ( dirb[XDIR_NumName] = nlen; /* Set name length */ dirb[XDIR_NumSec] = 1 + n_c1; /* Set secondary count (C0 + C1s) */ - st_word(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ + st_16(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ } #endif /* !FF_FS_READONLY */ @@ -2425,10 +2425,10 @@ static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ #if FF_MAX_LFN < 255 if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */ #endif - if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ + if (ld_16(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare the name */ if ((di % SZDIRE) == 0) di += 2; - if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; + if (ff_wtoupper(ld_16(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; } if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */ } @@ -2517,8 +2517,8 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */ if (res != FR_OK) return res; dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ - st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); - st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); + st_64(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); + st_64(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; /* Update the allocation status */ res = store_xdir(&dj); /* Store the object status */ if (res != FR_OK) return res; @@ -2534,7 +2534,7 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ for (n = 1; n < 100; n++) { - gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */ + gen_numname(dp->fn, sn, fs->lfnbuf, (WORD)n); /* Generate a numbered name */ res = dir_find(dp); /* Check if the name collides with existing SFN */ if (res != FR_OK) break; } @@ -2652,7 +2652,6 @@ static void get_fileinfo ( #endif - fno->fname[0] = 0; /* Invaidate file info */ if (dp->sect == 0) return; /* Exit if read pointer has reached end of directory */ #if FF_USE_LFN /* LFN configuration */ @@ -2667,7 +2666,7 @@ static void get_fileinfo ( di = 0; break; } if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ - wc = ld_word(fs->dirbuf + si); si += 2; nc++; /* Get a character */ + wc = ld_16(fs->dirbuf + si); si += 2; nc++; /* Get a character */ if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ hs = wc; continue; /* Get low surrogate */ } @@ -2683,10 +2682,14 @@ static void get_fileinfo ( fno->fname[di] = 0; /* Terminate the name */ fno->altname[0] = 0; /* exFAT does not support SFN */ - fno->fattrib = fs->dirbuf[XDIR_Attr] & AM_MASKX; /* Attribute */ - fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */ - fno->ftime = ld_word(fs->dirbuf + XDIR_ModTime + 0); /* Time */ - fno->fdate = ld_word(fs->dirbuf + XDIR_ModTime + 2); /* Date */ + fno->fattrib = fs->dirbuf[XDIR_Attr] & AM_MASKX; /* Attribute */ + fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_64(fs->dirbuf + XDIR_FileSize); /* Size */ + fno->ftime = ld_16(fs->dirbuf + XDIR_ModTime + 0); /* Last modified time */ + fno->fdate = ld_16(fs->dirbuf + XDIR_ModTime + 2); /* Last modified date */ +#if FF_FS_CRTIME + fno->crtime = ld_16(fs->dirbuf + XDIR_CrtTime + 0); /* Created time */ + fno->crdate = ld_16(fs->dirbuf + XDIR_CrtTime + 2); /* Created date */ +#endif return; } else #endif @@ -2763,10 +2766,14 @@ static void get_fileinfo ( fno->fname[di] = 0; /* Terminate the SFN */ #endif - fno->fattrib = dp->dir[DIR_Attr] & AM_MASK; /* Attribute */ - fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */ - fno->ftime = ld_word(dp->dir + DIR_ModTime + 0); /* Time */ - fno->fdate = ld_word(dp->dir + DIR_ModTime + 2); /* Date */ + fno->fattrib = dp->dir[DIR_Attr] & AM_MASK; /* Attribute */ + fno->fsize = ld_32(dp->dir + DIR_FileSize); /* Size */ + fno->ftime = ld_16(dp->dir + DIR_ModTime + 0); /* Last modified time */ + fno->fdate = ld_16(dp->dir + DIR_ModTime + 2); /* Last Modified date */ +#if FF_FS_CRTIME + fno->crtime = ld_16(dp->dir + DIR_CrtTime + 0); /* Created time */ + fno->crdate = ld_16(dp->dir + DIR_CrtTime + 2); /* Created date */ +#endif } #endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ @@ -3100,7 +3107,7 @@ static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ dp->obj.c_ofs = fs->cdc_ofs; res = load_obj_xdir(&dj, &dp->obj); if (res != FR_OK) return res; - dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize); + dp->obj.objsize = ld_32(fs->dirbuf + XDIR_FileSize); dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; } #endif @@ -3261,14 +3268,14 @@ static int test_gpt_header ( /* 0:Invalid, 1:Valid */ if (memcmp(gpth + GPTH_Sign, "EFI PART" "\0\0\1", 12)) return 0; /* Check signature and version (1.0) */ - hlen = ld_dword(gpth + GPTH_Size); /* Check header size */ + hlen = ld_32(gpth + GPTH_Size); /* Check header size */ if (hlen < 92 || hlen > FF_MIN_SS) return 0; for (i = 0, bcc = 0xFFFFFFFF; i < hlen; i++) { /* Check header BCC */ bcc = crc32(bcc, i - GPTH_Bcc < 4 ? 0 : gpth[i]); } - if (~bcc != ld_dword(gpth + GPTH_Bcc)) return 0; - if (ld_dword(gpth + GPTH_PteSize) != SZ_GPTE) return 0; /* Table entry size (must be SZ_GPTE bytes) */ - if (ld_dword(gpth + GPTH_PtNum) > 128) return 0; /* Table size (must be 128 entries or less) */ + if (~bcc != ld_32(gpth + GPTH_Bcc)) return 0; + if (ld_32(gpth + GPTH_PteSize) != SZ_GPTE) return 0; /* Table entry size (must be SZ_GPTE bytes) */ + if (ld_32(gpth + GPTH_PtNum) > 128) return 0; /* Table size (must be 128 entries or less) */ return 1; } @@ -3315,7 +3322,7 @@ static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS, fs->wflag = 0; fs->winsect = (LBA_t)0 - 1; /* Invaidate window */ if (move_window(fs, sect) != FR_OK) return 4; /* Load the boot sector */ - sign = ld_word(fs->win + BS_55AA); + sign = ld_16(fs->win + BS_55AA); #if FF_FS_EXFAT if (sign == 0xAA55 && !memcmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* It is an exFAT VBR */ #endif @@ -3325,15 +3332,15 @@ static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS, return 0; /* It is an FAT32 VBR */ } /* FAT volumes created in the early MS-DOS era lack BS_55AA and BS_FilSysType, so FAT VBR needs to be identified without them. */ - w = ld_word(fs->win + BPB_BytsPerSec); + w = ld_16(fs->win + BPB_BytsPerSec); b = fs->win[BPB_SecPerClus]; if ((w & (w - 1)) == 0 && w >= FF_MIN_SS && w <= FF_MAX_SS /* Properness of sector size (512-4096 and 2^n) */ && b != 0 && (b & (b - 1)) == 0 /* Properness of cluster size (2^n) */ - && ld_word(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of number of reserved sectors (MNBZ) */ + && ld_16(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of number of reserved sectors (MNBZ) */ && (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of number of FATs (1 or 2) */ - && ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir size (MNBZ) */ - && (ld_word(fs->win + BPB_TotSec16) >= 128 || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume size (>=128) */ - && ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */ + && ld_16(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir size (MNBZ) */ + && (ld_16(fs->win + BPB_TotSec16) >= 128 || ld_32(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume size (>=128) */ + && ld_16(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */ return 0; /* It can be presumed an FAT VBR */ } } @@ -3365,14 +3372,14 @@ static UINT find_volume ( /* Returns BS status found in the hosting drive */ if (move_window(fs, 1) != FR_OK) return 4; /* Load GPT header sector (next to MBR) */ if (!test_gpt_header(fs->win)) return 3; /* Check if GPT header is valid */ - n_ent = ld_dword(fs->win + GPTH_PtNum); /* Number of entries */ - pt_lba = ld_qword(fs->win + GPTH_PtOfs); /* Table location */ + n_ent = ld_32(fs->win + GPTH_PtNum); /* Number of entries */ + pt_lba = ld_64(fs->win + GPTH_PtOfs); /* Table location */ for (v_ent = i = 0; i < n_ent; i++) { /* Find FAT partition */ if (move_window(fs, pt_lba + i * SZ_GPTE / SS(fs)) != FR_OK) return 4; /* PT sector */ ofs = i * SZ_GPTE % SS(fs); /* Offset in the sector */ if (!memcmp(fs->win + ofs + GPTE_PtGuid, GUID_MS_Basic, 16)) { /* MS basic data partition? */ v_ent++; - fmt = check_fs(fs, ld_qword(fs->win + ofs + GPTE_FstLba)); /* Load VBR and check status */ + fmt = check_fs(fs, ld_64(fs->win + ofs + GPTE_FstLba)); /* Load VBR and check status */ if (part == 0 && fmt <= 1) return fmt; /* Auto search (valid FAT volume found first) */ if (part != 0 && v_ent == part) return fmt; /* Forced partition order (regardless of it is valid or not) */ } @@ -3382,7 +3389,7 @@ static UINT find_volume ( /* Returns BS status found in the hosting drive */ #endif if (FF_MULTI_PARTITION && part > 4) return 3; /* MBR has 4 partitions max */ for (i = 0; i < 4; i++) { /* Load partition offset in the MBR */ - mbr_pt[i] = ld_dword(fs->win + MBR_Table + i * SZ_PTE + PTE_StLba); + mbr_pt[i] = ld_32(fs->win + MBR_Table + i * SZ_PTE + PTE_StLba); } i = part ? part - 1 : 0; /* Table index to find first */ do { /* Find an FAT volume */ @@ -3469,16 +3476,16 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; - if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ + if (ld_16(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ return FR_NO_FILESYSTEM; } - maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA of the volume + 1 */ + maxlba = ld_64(fs->win + BPB_TotSecEx) + bsect; /* Last LBA of the volume + 1 */ if (!FF_LBA64 && maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be accessed in 32-bit LBA) */ - fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ + fs->fsize = ld_32(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ @@ -3486,16 +3493,16 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768 sectors) */ - nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ + nclst = ld_32(fs->win + BPB_NumClusEx); /* Number of clusters */ if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ fs->n_fatent = nclst + 2; /* Boundaries and Limits */ fs->volbase = bsect; - fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); - fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); + fs->database = bsect + ld_32(fs->win + BPB_DataOfsEx); + fs->fatbase = bsect + ld_32(fs->win + BPB_FatOfsEx); if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size required) */ - fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); + fs->dirbase = ld_32(fs->win + BPB_RootClusEx); /* Get bitmap location and check if it is contiguous (implementation assumption) */ so = i = 0; @@ -3505,15 +3512,15 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ if (move_window(fs, clst2sect(fs, (DWORD)fs->dirbase) + so) != FR_OK) return FR_DISK_ERR; so++; } - if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */ + if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */ i = (i + SZDIRE) % SS(fs); /* Next entry */ } - bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */ + bcl = ld_32(fs->win + i + 20); /* Bitmap cluster */ if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM; /* (Wrong cluster#) */ fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */ for (;;) { /* Check if bitmap is contiguous */ if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR; - cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4); + cv = ld_32(fs->win + bcl % (SS(fs) / 4) * 4); if (cv == 0xFFFFFFFF) break; /* Last link? */ if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented bitmap? */ } @@ -3526,10 +3533,10 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ } else #endif /* FF_FS_EXFAT */ { - if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ + if (ld_16(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ - fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ - if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); + fasize = ld_16(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ + if (fasize == 0) fasize = ld_32(fs->win + BPB_FATSz32); fs->fsize = fasize; fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ @@ -3539,13 +3546,13 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ - fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ + fs->n_rootdir = ld_16(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ - tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ - if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); + tsect = ld_16(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ + if (tsect == 0) tsect = ld_32(fs->win + BPB_TotSec32); - nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ + nrsv = ld_16(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ /* Determine the FAT sub type */ @@ -3565,9 +3572,9 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ fs->fatbase = bsect + nrsv; /* FAT start sector */ fs->database = bsect + sysect; /* Data start sector */ if (fmt == FS_FAT32) { - if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ + if (ld_16(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ - fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ + fs->dirbase = ld_32(fs->win + BPB_RootClus32); /* Root directory start cluster */ szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ } else { if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ @@ -3582,19 +3589,19 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Invalidate cluster allocation information */ fs->fsi_flag = 0x80; /* Disable FSInfo by default */ if (fmt == FS_FAT32 - && ld_word(fs->win + BPB_FSInfo32) == 1 /* FAT32: Enable FSInfo feature only if FSInfo sector is next to VBR */ + && ld_16(fs->win + BPB_FSInfo32) == 1 /* FAT32: Enable FSInfo feature only if FSInfo sector is next to VBR */ && move_window(fs, bsect + 1) == FR_OK) { fs->fsi_flag = 0; - if ( ld_dword(fs->win + FSI_LeadSig) == 0x41615252 /* Load FSInfo data if available */ - && ld_dword(fs->win + FSI_StrucSig) == 0x61417272 - && ld_dword(fs->win + FSI_TrailSig) == 0xAA550000) + if ( ld_32(fs->win + FSI_LeadSig) == 0x41615252 /* Load FSInfo data if available */ + && ld_32(fs->win + FSI_StrucSig) == 0x61417272 + && ld_32(fs->win + FSI_TrailSig) == 0xAA550000) { #if (FF_FS_NOFSINFO & 1) == 0 /* Get free cluster count if trust it */ - fs->free_clst = ld_dword(fs->win + FSI_Free_Count); + fs->free_clst = ld_32(fs->win + FSI_Free_Count); #endif #if (FF_FS_NOFSINFO & 2) == 0 /* Get next free cluster if rtust it */ - fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free); + fs->last_clst = ld_32(fs->win + FSI_Nxt_Free); #endif } } @@ -3739,18 +3746,19 @@ FRESULT f_open ( DIR dj; FATFS *fs; #if !FF_FS_READONLY - DWORD cl, bcs, clst, tm; + DWORD cl, bcs, clst; LBA_t sc; FSIZE_t ofs; #endif DEF_NAMBUF - if (!fp) return FR_INVALID_OBJECT; + if (!fp) return FR_INVALID_OBJECT; /* Reject null pointer */ - /* Get logical drive number */ + /* Get logical drive number and mount the volume if needed */ mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND; res = mount_volume(&path, &fs, mode); + if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); @@ -3778,11 +3786,11 @@ FRESULT f_open ( } mode |= FA_CREATE_ALWAYS; /* File is created */ } - else { /* Any object with the same name is already existing */ - if (dj.obj.attr & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; + else { /* An object with the same name is already existing */ + if (mode & FA_CREATE_NEW) { + res = FR_EXIST; /* Cannot create as new file */ } else { - if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */ + if (dj.obj.attr & (AM_RDO | AM_DIR)) res = FR_DENIED; /* Cannot overwrite it (R/O or DIR) */ } } if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate the file if overwrite mode */ @@ -3791,11 +3799,11 @@ FRESULT f_open ( /* Get current allocation info */ fp->obj.fs = fs; init_alloc_info(fs, &fp->obj); - /* Set directory entry block initial state */ + /* Set exFAT directory entry block initial state */ memset(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */ memset(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */ fs->dirbuf[XDIR_Attr] = AM_ARC; - st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME()); + st_32(fs->dirbuf + XDIR_CrtTime, GET_FATTIME()); /* Set created time */ fs->dirbuf[XDIR_GenFlags] = 1; res = store_xdir(&dj); if (res == FR_OK && fp->obj.sclust != 0) { /* Remove the cluster chain if exist */ @@ -3805,14 +3813,12 @@ FRESULT f_open ( } else #endif { - /* Set directory entry initial state */ - tm = GET_FATTIME(); /* Set created time */ - st_dword(dj.dir + DIR_CrtTime, tm); - st_dword(dj.dir + DIR_ModTime, tm); + /* Set FAT directory entry initial state */ + st_32(dj.dir + DIR_CrtTime, GET_FATTIME()); /* Set created time */ cl = ld_clust(fs, dj.dir); /* Get current cluster chain */ dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */ st_clust(fs, dj.dir, 0); /* Reset file allocation info */ - st_dword(dj.dir + DIR_FileSize, 0); + st_32(dj.dir + DIR_FileSize, 0); fs->wflag = 1; if (cl != 0) { /* Remove the cluster chain if exist */ sc = fs->winsect; @@ -3868,7 +3874,7 @@ FRESULT f_open ( #endif { fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */ - fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize); + fp->obj.objsize = ld_32(dj.dir + DIR_FileSize); } #if FF_USE_FASTSEEK fp->cltbl = 0; /* Disable fast seek mode */ @@ -4153,7 +4159,6 @@ FRESULT f_sync ( { FRESULT res; FATFS *fs; - DWORD tm; BYTE *dir; @@ -4167,7 +4172,6 @@ FRESULT f_sync ( } #endif /* Update the directory entry */ - tm = GET_FATTIME(); /* Modified time */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */ @@ -4181,15 +4185,17 @@ FRESULT f_sync ( INIT_NAMBUF(fs); res = load_obj_xdir(&dj, &fp->obj); /* Load directory entry block */ if (res == FR_OK) { - fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ - fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */ - st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); /* Update start cluster */ - st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); /* Update file size */ - st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); /* (FatFs does not support Valid File Size feature) */ - st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */ + fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */ + st_32(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); /* Update start cluster */ + st_64(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); /* Update file size */ + st_64(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); /* (FatFs does not support Valid File Size feature) */ + st_32(fs->dirbuf + XDIR_ModTime, GET_FATTIME()); /* Update modified time */ fs->dirbuf[XDIR_ModTime10] = 0; - st_dword(fs->dirbuf + XDIR_AccTime, 0); - res = store_xdir(&dj); /* Restore it to the directory */ + fs->dirbuf[XDIR_ModTZ] = 0; + st_32(fs->dirbuf + XDIR_AccTime, 0); /* Invalidate last access time */ + fs->dirbuf[XDIR_AccTZ] = 0; + res = store_xdir(&dj); /* Restore it to the directory */ if (res == FR_OK) { res = sync_fs(fs); fp->flag &= (BYTE)~FA_MODIFIED; @@ -4203,13 +4209,13 @@ FRESULT f_sync ( res = move_window(fs, fp->dir_sect); if (res == FR_OK) { dir = fp->dir_ptr; - dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ - st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */ - st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ - st_dword(dir + DIR_ModTime, tm); /* Update modified time */ - st_word(dir + DIR_LstAccDate, 0); + dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */ + st_32(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ + st_32(dir + DIR_ModTime, GET_FATTIME()); /* Update modified time */ + st_16(dir + DIR_LstAccDate, 0); /* Invalidate last access date */ fs->wflag = 1; - res = sync_fs(fs); /* Restore it to the directory */ + res = sync_fs(fs); /* Restore it to the directory */ fp->flag &= (BYTE)~FA_MODIFIED; } } @@ -4294,8 +4300,7 @@ FRESULT f_chdir ( DEF_NAMBUF - /* Get logical drive */ - res = mount_volume(&path, &fs, 0); + res = mount_volume(&path, &fs, 0); /* Get logical drive and mount the volume if needed */ if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); @@ -4314,14 +4319,14 @@ FRESULT f_chdir ( if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { - fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ - fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ + fs->cdir = ld_32(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ + fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; fs->cdc_ofs = dj.blk_ofs; } else #endif { - fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ + fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ } } else { res = FR_NO_PATH; /* Reached but a file */ @@ -4619,10 +4624,9 @@ FRESULT f_opendir ( DEF_NAMBUF - if (!dp) return FR_INVALID_OBJECT; + if (!dp) return FR_INVALID_OBJECT; /* Reject null pointer */ - /* Get logical drive */ - res = mount_volume(&path, &fs, 0); + res = mount_volume(&path, &fs, 0); /* Get logical drive and mount the volume if needed */ if (res == FR_OK) { dp->obj.fs = fs; INIT_NAMBUF(fs); @@ -4731,6 +4735,8 @@ FRESULT f_readdir ( FREE_NAMBUF(); } } + + if (fno && res != FR_OK) fno->fname[0] = 0; /* Invalidate the file information if any error occured */ LEAVE_FF(fs, res); } @@ -4803,8 +4809,9 @@ FRESULT f_stat ( DEF_NAMBUF - /* Get logical drive */ + /* Get logical drive and mount the volume if needed */ res = mount_volume(&path, &dj.obj.fs, 0); + if (res == FR_OK) { INIT_NAMBUF(dj.obj.fs); res = follow_path(&dj, path); /* Follow the file path */ @@ -4818,6 +4825,7 @@ FRESULT f_stat ( FREE_NAMBUF(); } + if (fno && res != FR_OK) fno->fname[0] = 0; /* Invalidate the file information if any error occured */ LEAVE_FF(dj.obj.fs, res); } @@ -4842,8 +4850,9 @@ FRESULT f_getfree ( FFOBJID obj; - /* Get logical drive */ + /* Get logical drive and mount the volume if needed */ res = mount_volume(&path, &fs, 0); + if (res == FR_OK) { *fatfs = fs; /* Return ptr to the fs object */ /* If free_clst is valid, return it without full FAT scan */ @@ -4896,10 +4905,10 @@ FRESULT f_getfree ( if (res != FR_OK) break; } if (fs->fs_type == FS_FAT16) { - if (ld_word(fs->win + i) == 0) nfree++; /* FAT16: Is this cluster free? */ + if (ld_16(fs->win + i) == 0) nfree++; /* FAT16: Is this cluster free? */ i += 2; /* Next entry */ } else { - if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++; /* FAT32: Is this cluster free? */ + if ((ld_32(fs->win + i) & 0x0FFFFFFF) == 0) nfree++; /* FAT32: Is this cluster free? */ i += 4; /* Next entry */ } i %= SS(fs); @@ -4933,7 +4942,8 @@ FRESULT f_truncate ( DWORD ncl; - res = validate(&fp->obj, &fs); /* Check validity of the file object */ + /* Check validity of the file object */ + res = validate(&fp->obj, &fs); if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ @@ -4988,8 +4998,9 @@ FRESULT f_unlink ( DEF_NAMBUF - /* Get logical drive */ + /* Get logical drive and mount the volume if needed */ res = mount_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); @@ -5080,7 +5091,9 @@ FRESULT f_mkdir ( DEF_NAMBUF - res = mount_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + /* Get logical drive and mount the volume if needed */ + res = mount_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); @@ -5104,7 +5117,7 @@ FRESULT f_mkdir ( memset(fs->win + DIR_Name, ' ', 11); /* Create "." entry */ fs->win[DIR_Name] = '.'; fs->win[DIR_Attr] = AM_DIR; - st_dword(fs->win + DIR_ModTime, tm); + st_32(fs->win + DIR_ModTime, tm); st_clust(fs, fs->win, dcl); memcpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */ fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust; @@ -5117,17 +5130,19 @@ FRESULT f_mkdir ( if (res == FR_OK) { #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */ - st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */ - st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ - st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* Directory size needs to be valid */ - st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs)); - fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */ - fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ + st_32(fs->dirbuf + XDIR_CrtTime, tm); /* Created time */ + st_32(fs->dirbuf + XDIR_ModTime, tm); + st_32(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ + st_32(fs->dirbuf + XDIR_FileSize, (DWORD)fs->csize * SS(fs)); /* Directory size needs to be valid */ + st_32(fs->dirbuf + XDIR_ValidFileSize, (DWORD)fs->csize * SS(fs)); + fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */ + fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ res = store_xdir(&dj); } else #endif { - st_dword(dj.dir + DIR_ModTime, tm); /* Created time */ + st_32(dj.dir + DIR_CrtTime, tm); /* Created time */ + st_32(dj.dir + DIR_ModTime, tm); st_clust(fs, dj.dir, dcl); /* Table start cluster */ dj.dir[DIR_Attr] = AM_DIR; /* Attribute */ fs->wflag = 1; @@ -5165,8 +5180,11 @@ FRESULT f_rename ( DEF_NAMBUF - get_ldnumber(&path_new); /* Snip the drive number of new name off */ - res = mount_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */ + /* Snip the drive number of new name off */ + get_ldnumber(&path_new); + + /* Get logical drive of the old object */ + res = mount_volume(&path_old, &fs, FA_WRITE); if (res == FR_OK) { djo.obj.fs = fs; INIT_NAMBUF(fs); @@ -5193,10 +5211,10 @@ FRESULT f_rename ( res = dir_register(&djn); /* Register the new entry */ if (res == FR_OK) { nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName]; - nh = ld_word(fs->dirbuf + XDIR_NameHash); + nh = ld_16(fs->dirbuf + XDIR_NameHash); memcpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */ fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn; - st_word(fs->dirbuf + XDIR_NameHash, nh); + st_16(fs->dirbuf + XDIR_NameHash, nh); if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ /* Start of critical section where an interruption can cause a cross-link */ res = store_xdir(&djn); @@ -5264,7 +5282,7 @@ FRESULT f_rename ( FRESULT f_chmod ( const TCHAR* path, /* Pointer to the file path */ - BYTE attr, /* Attribute bits */ + BYTE attr, /* Attribute bits to set/clear */ BYTE mask /* Attribute mask to change */ ) { @@ -5274,7 +5292,9 @@ FRESULT f_chmod ( DEF_NAMBUF - res = mount_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + /* Get logical drive and mount the volume if needed */ + res = mount_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); @@ -5311,7 +5331,7 @@ FRESULT f_chmod ( FRESULT f_utime ( const TCHAR* path, /* Pointer to the file/directory name */ - const FILINFO* fno /* Pointer to the timestamp to be set */ + const FILINFO* fno /* Timestamp to be set */ ) { FRESULT res; @@ -5320,7 +5340,9 @@ FRESULT f_utime ( DEF_NAMBUF - res = mount_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + /* Get logical drive and mount the volume if needed */ + res = mount_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); @@ -5328,13 +5350,32 @@ FRESULT f_utime ( if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ if (res == FR_OK) { #if FF_FS_EXFAT - if (fs->fs_type == FS_EXFAT) { - st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + if (fno->fdate) { /* Change last modified time if needed */ + st_32(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + fs->dirbuf[XDIR_ModTime10] = 0; + fs->dirbuf[XDIR_ModTZ] = 0; + } +#if FF_FS_CRTIME + if (fno->crdate) { /* Change created time if needed */ + st_32(fs->dirbuf + XDIR_CrtTime, (DWORD)fno->crdate << 16 | fno->crtime); + fs->dirbuf[XDIR_CrtTime10] = 0; + fs->dirbuf[XDIR_CrtTZ] = 0; + } +#endif res = store_xdir(&dj); } else #endif - { - st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + { /* On the FAT volume */ + if (fno->fdate) { /* Change last modified time if needed */ + st_32(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + } +#if FF_FS_CRTIME + if (fno->crdate) { /* Change created time if needed */ + st_32(dj.dir + DIR_CrtTime, (DWORD)fno->crdate << 16 | fno->crtime); + dj.dir[DIR_CrtTime10] = 0; + } +#endif fs->wflag = 1; } if (res == FR_OK) { @@ -5368,8 +5409,8 @@ FRESULT f_getlabel ( UINT si, di; WCHAR wc; - /* Get logical drive */ - res = mount_volume(&path, &fs, 0); + + res = mount_volume(&path, &fs, 0); /* Get logical drive and mount the volume if needed */ /* Get volume label */ if (res == FR_OK && label) { @@ -5384,7 +5425,7 @@ FRESULT f_getlabel ( UINT nw; for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */ - wc = ld_word(dj.dir + XDIR_Label + si * 2); + wc = ld_16(dj.dir + XDIR_Label + si * 2); if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */ hs = wc; continue; } @@ -5443,7 +5484,7 @@ FRESULT f_getlabel ( default: /* FAT12/16 */ di = fs->win[BS_BootSig] == 0x29 ? BS_VolID : 0; } - *vsn = di ? ld_dword(fs->win + di) : 0; /* Get VSN in the VBR */ + *vsn = di ? ld_32(fs->win + di) : 0; /* Get VSN in the VBR */ } } @@ -5472,7 +5513,7 @@ FRESULT f_setlabel ( DWORD dc; #endif - /* Get logical drive */ + /* Get logical drive and mount the volume if needed */ res = mount_volume(&label, &fs, FA_WRITE); if (res != FR_OK) LEAVE_FF(fs, res); #if FF_STR_VOLUME_ID == 2 @@ -5489,13 +5530,13 @@ FRESULT f_setlabel ( if (dc == 0xFFFFFFFF || di >= 10) { /* Wrong surrogate or buffer overflow */ dc = 0; } else { - st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++; + st_16(dirvn + di * 2, (WCHAR)(dc >> 16)); di++; } } if (dc == 0 || strchr(&badchr[7], (int)dc) || di >= 11) { /* Check validity of the volume label */ LEAVE_FF(fs, FR_INVALID_NAME); } - st_word(dirvn + di * 2, (WCHAR)dc); di++; + st_16(dirvn + di * 2, (WCHAR)dc); di++; } } else #endif @@ -5749,7 +5790,7 @@ FRESULT f_forward ( #define N_SEC_TRACK 63 /* Sectors per track for determination of drive CHS */ #define GPT_ALIGN 0x100000 /* Alignment of partitions in GPT [byte] (>=128KB) */ -#define GPT_ITEMS 128 /* Number of GPT table size (>=128, sector aligned) */ +#define GPT_ITEMS 128 /* Number of GPT table items (>=128, sector aligned) */ /* Create partitions on the physical drive in format of MBR or GPT */ @@ -5809,8 +5850,8 @@ static FRESULT create_partition ( ofs = pi * SZ_GPTE % ss; memcpy(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16); /* Set partition GUID (Microsoft Basic Data) */ rnd = make_rand(rnd, buf + ofs + GPTE_UpGuid, 16); /* Set unique partition GUID */ - st_qword(buf + ofs + GPTE_FstLba, nxt_alloc); /* Set partition start LBA */ - st_qword(buf + ofs + GPTE_LstLba, nxt_alloc + sz_part - 1); /* Set partition end LBA */ + st_64(buf + ofs + GPTE_FstLba, nxt_alloc); /* Set partition start LBA */ + st_64(buf + ofs + GPTE_LstLba, nxt_alloc + sz_part - 1); /* Set partition end LBA */ nxt_alloc += sz_part; /* Next allocatable LBA */ } if ((pi + 1) * SZ_GPTE % ss == 0) { /* Write the sector buffer if it is filled up */ @@ -5823,32 +5864,32 @@ static FRESULT create_partition ( /* Create primary GPT header */ memset(buf, 0, ss); memcpy(buf + GPTH_Sign, "EFI PART" "\0\0\1\0" "\x5C\0\0", 16); /* Signature, version (1.0) and size (92) */ - st_dword(buf + GPTH_PtBcc, ~bcc); /* Table check sum */ - st_qword(buf + GPTH_CurLba, 1); /* LBA of this header */ - st_qword(buf + GPTH_BakLba, sz_drv - 1); /* LBA of secondary header */ - st_qword(buf + GPTH_FstLba, 2 + sz_ptbl); /* LBA of first allocatable sector */ - st_qword(buf + GPTH_LstLba, top_bpt - 1); /* LBA of last allocatable sector */ - st_dword(buf + GPTH_PteSize, SZ_GPTE); /* Size of a table entry */ - st_dword(buf + GPTH_PtNum, GPT_ITEMS); /* Number of table entries */ - st_dword(buf + GPTH_PtOfs, 2); /* LBA of this table */ + st_32(buf + GPTH_PtBcc, ~bcc); /* Table check sum */ + st_64(buf + GPTH_CurLba, 1); /* LBA of this header */ + st_64(buf + GPTH_BakLba, sz_drv - 1); /* LBA of secondary header */ + st_64(buf + GPTH_FstLba, 2 + sz_ptbl); /* LBA of first allocatable sector */ + st_64(buf + GPTH_LstLba, top_bpt - 1); /* LBA of last allocatable sector */ + st_32(buf + GPTH_PteSize, SZ_GPTE); /* Size of a table entry */ + st_32(buf + GPTH_PtNum, GPT_ITEMS); /* Number of table entries */ + st_32(buf + GPTH_PtOfs, 2); /* LBA of this table */ rnd = make_rand(rnd, buf + GPTH_DskGuid, 16); /* Disk GUID */ for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */ - st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */ + st_32(buf + GPTH_Bcc, ~bcc); /* Header check sum */ if (disk_write(drv, buf, 1, 1) != RES_OK) return FR_DISK_ERR; /* Create secondary GPT header */ - st_qword(buf + GPTH_CurLba, sz_drv - 1); /* LBA of this header */ - st_qword(buf + GPTH_BakLba, 1); /* LBA of primary header */ - st_qword(buf + GPTH_PtOfs, top_bpt); /* LBA of this table */ - st_dword(buf + GPTH_Bcc, 0); + st_64(buf + GPTH_CurLba, sz_drv - 1); /* LBA of this header */ + st_64(buf + GPTH_BakLba, 1); /* LBA of primary header */ + st_64(buf + GPTH_PtOfs, top_bpt); /* LBA of this table */ + st_32(buf + GPTH_Bcc, 0); for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */ - st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */ + st_32(buf + GPTH_Bcc, ~bcc); /* Header check sum */ if (disk_write(drv, buf, sz_drv - 1, 1) != RES_OK) return FR_DISK_ERR; /* Create protective MBR */ memset(buf, 0, ss); - memcpy(buf + MBR_Table, gpt_mbr, 16); /* Create a GPT partition */ - st_word(buf + BS_55AA, 0xAA55); + memcpy(buf + MBR_Table, gpt_mbr, 16); /* Create a GPT partition */ + st_16(buf + BS_55AA, 0xAA55); if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; } else @@ -5867,8 +5908,8 @@ static FRESULT create_partition ( if (nxt_alloc32 + sz_part32 > sz_drv32 || nxt_alloc32 + sz_part32 < nxt_alloc32) sz_part32 = sz_drv32 - nxt_alloc32; /* Clip at drive size */ if (sz_part32 == 0) break; /* End of table or no sector to allocate? */ - st_dword(pte + PTE_StLba, nxt_alloc32); /* Partition start LBA sector */ - st_dword(pte + PTE_SizLba, sz_part32); /* Size of partition [sector] */ + st_32(pte + PTE_StLba, nxt_alloc32); /* Partition start LBA sector */ + st_32(pte + PTE_SizLba, sz_part32); /* Size of partition [sector] */ pte[PTE_System] = sys; /* System type */ cy = (UINT)(nxt_alloc32 / n_sc / n_hd); /* Partitio start CHS cylinder */ @@ -5888,7 +5929,7 @@ static FRESULT create_partition ( pte += SZ_PTE; /* Next entry */ } - st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ + st_16(buf + BS_55AA, 0xAA55); /* MBR signature */ if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the MBR */ } @@ -5922,7 +5963,7 @@ FRESULT f_mkfs ( /* Check mounted drive and clear work area */ - vol = get_ldnumber(&path); /* Get target logical drive */ + vol = get_ldnumber(&path); /* Get logical drive number to be formatted */ if (vol < 0) return FR_INVALID_DRIVE; if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the fs object if mounted */ pdrv = LD2PD(vol); /* Hosting physical drive */ @@ -5966,7 +6007,7 @@ FRESULT f_mkfs ( if (FF_MULTI_PARTITION && ipart != 0) { /* Is the volume associated with any specific partition? */ /* Get partition location from the existing partition table */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load MBR */ - if (ld_word(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ + if (ld_16(buf + BS_55AA) != 0xAA55) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if MBR is valid */ #if FF_LBA64 if (buf[MBR_Table + PTE_System] == 0xEE) { /* GPT protective MBR? */ DWORD n_ent, ofs; @@ -5975,14 +6016,14 @@ FRESULT f_mkfs ( /* Get the partition location from GPT */ if (disk_read(pdrv, buf, 1, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Load GPT header sector (next to MBR) */ if (!test_gpt_header(buf)) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if GPT header is valid */ - n_ent = ld_dword(buf + GPTH_PtNum); /* Number of entries */ - pt_lba = ld_qword(buf + GPTH_PtOfs); /* Table start sector */ + n_ent = ld_32(buf + GPTH_PtNum); /* Number of entries */ + pt_lba = ld_64(buf + GPTH_PtOfs); /* Table start sector */ ofs = i = 0; while (n_ent) { /* Find MS Basic partition with order of ipart */ if (ofs == 0 && disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Get PT sector */ if (!memcmp(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16) && ++i == ipart) { /* MS basic data partition? */ - b_vol = ld_qword(buf + ofs + GPTE_FstLba); - sz_vol = ld_qword(buf + ofs + GPTE_LstLba) - b_vol + 1; + b_vol = ld_64(buf + ofs + GPTE_FstLba); + sz_vol = ld_64(buf + ofs + GPTE_LstLba) - b_vol + 1; break; } n_ent--; ofs = (ofs + SZ_GPTE) % ss; /* Next entry */ @@ -5994,8 +6035,8 @@ FRESULT f_mkfs ( { /* Get the partition location from MBR partition table */ pte = buf + (MBR_Table + (ipart - 1) * SZ_PTE); if (ipart > 4 || pte[PTE_System] == 0) LEAVE_MKFS(FR_MKFS_ABORTED); /* No partition? */ - b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ - sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ + b_vol = ld_32(pte + PTE_StLba); /* Get volume start sector */ + sz_vol = ld_32(pte + PTE_SizLba); /* Get volume size */ } } else { /* The volume is associated with a physical drive */ if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); @@ -6020,7 +6061,7 @@ FRESULT f_mkfs ( do { /* Pre-determine the FAT type */ if (FF_FS_EXFAT && (fsopt & FM_EXFAT)) { /* exFAT possible? */ - if ((fsopt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || sz_au > 128) { /* exFAT only, vol >= 64M sectors or sz_au > 128 sectors ? */ + if ((fsopt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || sz_au > 128) { /* exFAT only, vol >= 64M sectors or sz_au > 128 sectors? */ fsty = FS_EXFAT; break; } } @@ -6122,13 +6163,13 @@ FRESULT f_mkfs ( do { memset(buf, 0, sz_buf * ss); i = 0; /* Clear work area and reset write offset */ if (clu == 0) { /* Initialize FAT [0] and FAT[1] */ - st_dword(buf + i, 0xFFFFFFF8); i += 4; clu++; - st_dword(buf + i, 0xFFFFFFFF); i += 4; clu++; + st_32(buf + i, 0xFFFFFFF8); i += 4; clu++; + st_32(buf + i, 0xFFFFFFFF); i += 4; clu++; } do { /* Create chains of bitmap, up-case and root directory */ while (nbit != 0 && i < sz_buf * ss) { /* Create a chain */ - st_dword(buf + i, (nbit > 1) ? clu + 1 : 0xFFFFFFFF); + st_32(buf + i, (nbit > 1) ? clu + 1 : 0xFFFFFFFF); i += 4; clu++; nbit--; } if (nbit == 0 && j < 3) nbit = clen[j++]; /* Get next chain length */ @@ -6140,14 +6181,14 @@ FRESULT f_mkfs ( /* Initialize the root directory */ memset(buf, 0, sz_buf * ss); - buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry (no label) */ - buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */ - st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ - st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ - buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */ - st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */ - st_dword(buf + SZDIRE * 2 + 20, 2 + clen[0]); /* cluster */ - st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */ + buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry (no label) */ + buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */ + st_32(buf + SZDIRE * 1 + 20, 2); /* cluster */ + st_32(buf + SZDIRE * 1 + 24, szb_bit); /* size */ + buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */ + st_32(buf + SZDIRE * 2 + 4, sum); /* sum */ + st_32(buf + SZDIRE * 2 + 20, 2 + clen[0]); /* cluster */ + st_32(buf + SZDIRE * 2 + 24, szb_case); /* size */ sect = b_data + sz_au * (clen[0] + clen[1]); nsect = sz_au; /* Start of the root directory and number of sectors */ do { /* Fill root directory sectors */ n = (nsect > sz_buf) ? sz_buf : nsect; @@ -6162,28 +6203,28 @@ FRESULT f_mkfs ( /* Main record (+0) */ memset(buf, 0, ss); memcpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */ - st_qword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ - st_qword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ - st_dword(buf + BPB_FatOfsEx, (DWORD)(b_fat - b_vol)); /* FAT offset [sector] */ - st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ - st_dword(buf + BPB_DataOfsEx, (DWORD)(b_data - b_vol)); /* Data offset [sector] */ - st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ - st_dword(buf + BPB_RootClusEx, 2 + clen[0] + clen[1]); /* Root directory cluster number */ - st_dword(buf + BPB_VolIDEx, vsn); /* VSN */ - st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ + st_64(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ + st_64(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ + st_32(buf + BPB_FatOfsEx, (DWORD)(b_fat - b_vol)); /* FAT offset [sector] */ + st_32(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ + st_32(buf + BPB_DataOfsEx, (DWORD)(b_data - b_vol)); /* Data offset [sector] */ + st_32(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ + st_32(buf + BPB_RootClusEx, 2 + clen[0] + clen[1]); /* Root directory cluster number */ + st_32(buf + BPB_VolIDEx, vsn); /* VSN */ + st_16(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ for (buf[BPB_SecPerClusEx] = 0, i = sz_au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ buf[BPB_NumFATsEx] = 1; /* Number of FATs */ buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */ - st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ - st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ + st_16(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ + st_16(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ for (i = sum = 0; i < ss; i++) { /* VBR checksum */ if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); } if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Extended bootstrap record (+1..+8) */ memset(buf, 0, ss); - st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ + st_16(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ for (j = 1; j < 9; j++) { for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); @@ -6195,7 +6236,7 @@ FRESULT f_mkfs ( if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); } /* Sum record (+11) */ - for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ + for (i = 0; i < ss; i += 4) st_32(buf + i, sum); /* Fill with checksum value */ if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); } @@ -6283,48 +6324,48 @@ FRESULT f_mkfs ( /* Create FAT VBR */ memset(buf, 0, ss); memcpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11); /* Boot jump code (x86), OEM name */ - st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ + st_16(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ - st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ + st_16(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ buf[BPB_NumFATs] = (BYTE)n_fat; /* Number of FATs */ - st_word(buf + BPB_RootEntCnt, (WORD)((fsty == FS_FAT32) ? 0 : n_root)); /* Number of root directory entries */ + st_16(buf + BPB_RootEntCnt, (WORD)((fsty == FS_FAT32) ? 0 : n_root)); /* Number of root directory entries */ if (sz_vol < 0x10000) { - st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ + st_16(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ } else { - st_dword(buf + BPB_TotSec32, (DWORD)sz_vol); /* Volume size in 32-bit LBA */ + st_32(buf + BPB_TotSec32, (DWORD)sz_vol); /* Volume size in 32-bit LBA */ } buf[BPB_Media] = 0xF8; /* Media descriptor byte */ - st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ - st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ - st_dword(buf + BPB_HiddSec, (DWORD)b_vol); /* Volume offset in the physical drive [sector] */ + st_16(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ + st_16(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ + st_32(buf + BPB_HiddSec, (DWORD)b_vol); /* Volume offset in the physical drive [sector] */ if (fsty == FS_FAT32) { - st_dword(buf + BS_VolID32, vsn); /* VSN */ - st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ - st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ - st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ - st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ + st_32(buf + BS_VolID32, vsn); /* VSN */ + st_32(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ + st_32(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ + st_16(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ + st_16(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig32] = 0x29; /* Extended boot signature */ memcpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ } else { - st_dword(buf + BS_VolID, vsn); /* VSN */ - st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ + st_32(buf + BS_VolID, vsn); /* VSN */ + st_16(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ buf[BS_BootSig] = 0x29; /* Extended boot signature */ memcpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ } - st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ + st_16(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */ /* Create FSINFO record if needed */ if (fsty == FS_FAT32) { disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ memset(buf, 0, ss); - st_dword(buf + FSI_LeadSig, 0x41615252); - st_dword(buf + FSI_StrucSig, 0x61417272); - st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ - st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ - st_word(buf + BS_55AA, 0xAA55); + st_32(buf + FSI_LeadSig, 0x41615252); + st_32(buf + FSI_StrucSig, 0x61417272); + st_32(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + st_32(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ + st_16(buf + BS_55AA, 0xAA55); disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ } @@ -6334,11 +6375,11 @@ FRESULT f_mkfs ( sect = b_fat; /* FAT start sector */ for (i = 0; i < n_fat; i++) { /* Initialize FATs each */ if (fsty == FS_FAT32) { - st_dword(buf + 0, 0xFFFFFFF8); /* FAT[0] */ - st_dword(buf + 4, 0xFFFFFFFF); /* FAT[1] */ - st_dword(buf + 8, 0x0FFFFFFF); /* FAT[2] (root directory at cluster# 2) */ + st_32(buf + 0, 0xFFFFFFF8); /* FAT[0] */ + st_32(buf + 4, 0xFFFFFFFF); /* FAT[1] */ + st_32(buf + 8, 0x0FFFFFFF); /* FAT[2] (root directory at cluster# 2) */ } else { - st_dword(buf + 0, (fsty == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* FAT[0] and FAT[1] */ + st_32(buf + 0, (fsty == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* FAT[0] and FAT[1] */ } nsect = sz_fat; /* Number of FAT sectors */ do { /* Fill FAT sectors */ @@ -6480,12 +6521,12 @@ TCHAR* f_gets ( #elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ f_read(fp, s, 2, &rc); /* Get a code unit */ if (rc != 2) break; /* EOF? */ - dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + dc = (FF_STRF_ENCODE == 1) ? ld_16(s) : s[0] << 8 | s[1]; if (IsSurrogateL(dc)) continue; /* Broken surrogate pair? */ if (IsSurrogateH(dc)) { /* High surrogate? */ f_read(fp, s, 2, &rc); /* Get low surrogate */ if (rc != 2) break; /* EOF? */ - wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + wc = (FF_STRF_ENCODE == 1) ? ld_16(s) : s[0] << 8 | s[1]; if (!IsSurrogateL(wc)) continue; /* Broken surrogate pair? */ dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF); /* Merge surrogate pair */ } @@ -6663,11 +6704,11 @@ static void putc_bfd (putbuff* pb, TCHAR c) #if FF_STRF_ENCODE == 1 /* Write a code point in UTF-16LE */ if (hs != 0) { /* Surrogate pair? */ - st_word(&pb->buf[i], hs); + st_16(&pb->buf[i], hs); i += 2; nc++; } - st_word(&pb->buf[i], wc); + st_16(&pb->buf[i], wc); i += 2; #elif FF_STRF_ENCODE == 2 /* Write a code point in UTF-16BE */ if (hs != 0) { /* Surrogate pair? */ diff --git a/source/ff.h b/source/ff.h index a3eb2eb..dc52c57 100644 --- a/source/ff.h +++ b/source/ff.h @@ -1,8 +1,8 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem module R0.15a / +/ FatFs - Generic FAT Filesystem module R0.15b / /-----------------------------------------------------------------------------/ / -/ Copyright (C) 2024, ChaN, all right reserved. +/ Copyright (C) 2025, ChaN, all right reserved. / / FatFs module is an open source software. Redistribution and use of FatFs in / source and binary forms, with or without modification, are permitted provided @@ -20,7 +20,7 @@ #ifndef FF_DEFINED -#define FF_DEFINED 5380 /* Revision ID */ +#define FF_DEFINED 5385 /* Revision ID */ #ifdef __cplusplus extern "C" { @@ -131,11 +131,11 @@ extern const char* VolumeStr[FF_VOLUMES]; /* User defined volume ID table */ /* Filesystem object structure (FATFS) */ typedef struct { - BYTE fs_type; /* Filesystem type (0:blank filesystem object) */ + BYTE fs_type; /* Filesystem type (0:not mounted) */ BYTE pdrv; /* Volume hosting physical drive */ BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */ BYTE n_fats; /* Number of FATs (1 or 2) */ - BYTE wflag; /* win[] status (1:dirty) */ + BYTE wflag; /* win[] status (b0:dirty) */ BYTE fsi_flag; /* Allocation information control (b7:disabled, b0:dirty) */ WORD id; /* Volume mount ID */ WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ @@ -144,33 +144,29 @@ typedef struct { WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ #endif #if FF_USE_LFN - WCHAR* lfnbuf; /* LFN working buffer */ -#endif -#if FF_FS_EXFAT - BYTE* dirbuf; /* Directory entry block scratch pad buffer for exFAT */ + WCHAR *lfnbuf; /* LFN working buffer */ #endif #if !FF_FS_READONLY - DWORD last_clst; /* Last allocated cluster (Unknown if >= n_fatent) */ - DWORD free_clst; /* Number of free clusters (Unknown if >= n_fatent-2) */ + DWORD last_clst; /* Last allocated cluster (Unknown if >=n_fatent) */ + DWORD free_clst; /* Number of free clusters (Unknown if >=fs->n_fatent-2) */ #endif #if FF_FS_RPATH DWORD cdir; /* Current directory start cluster (0:root) */ -#if FF_FS_EXFAT - DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ - DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ - DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ -#endif #endif DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ DWORD fsize; /* Number of sectors per FAT */ + LBA_t winsect; /* Current sector appearing in the win[] */ LBA_t volbase; /* Volume base sector */ LBA_t fatbase; /* FAT base sector */ LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */ LBA_t database; /* Data base sector */ #if FF_FS_EXFAT LBA_t bitbase; /* Allocation bitmap base sector */ + BYTE *dirbuf; /* Directory entry block scratchpad buffer for exFAT */ + DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ + DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ + DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ #endif - LBA_t winsect; /* Current sector appearing in the win[] */ BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ } FATFS; @@ -190,7 +186,7 @@ typedef struct { DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ - DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ + DWORD c_ofs; /* Offset in the containing directory (valid when in file object and sclust != 0) */ #endif #if FF_FS_LOCK UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ @@ -247,6 +243,10 @@ typedef struct { FSIZE_t fsize; /* File size */ WORD fdate; /* Modified date */ WORD ftime; /* Modified time */ +#if FF_FS_CRTIME + WORD crdate; /* Created date */ + WORD crtime; /* Created time */ +#endif BYTE fattrib; /* File attribute */ #if FF_USE_LFN TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */ diff --git a/source/ffconf.h b/source/ffconf.h index e3d20e6..ea54af2 100644 --- a/source/ffconf.h +++ b/source/ffconf.h @@ -2,7 +2,7 @@ / Configurations of FatFs Module /---------------------------------------------------------------------------*/ -#define FFCONF_DEF 5380 /* Revision ID */ +#define FFCONF_DEF 5385 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations @@ -57,15 +57,15 @@ #define FF_USE_STRFUNC 0 -#define FF_PRINT_LLI 0 -#define FF_PRINT_FLOAT 0 +#define FF_PRINT_LLI 1 +#define FF_PRINT_FLOAT 1 #define FF_STRF_ENCODE 3 -/* FF_USE_STRFUNC switches the string API functions, f_gets(), f_putc(), f_puts() -/ and f_printf(). +/* FF_USE_STRFUNC switches string API functions, f_gets(), f_putc(), f_puts() and +/ f_printf(). / / 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect. -/ 1: Enable without LF - CRLF conversion. -/ 2: Enable with LF - CRLF conversion. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. / / FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2 / makes f_printf() support floating point argument. These features want C99 or later. @@ -238,9 +238,9 @@ #define FF_FS_NORTC 0 -#define FF_NORTC_MON 11 +#define FF_NORTC_MON 6 #define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2024 +#define FF_NORTC_YEAR 2025 /* The option FF_FS_NORTC switches timestamp feature. If the system does not have / an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the / timestamp feature. Every object modified by FatFs will have a fixed timestamp @@ -251,9 +251,14 @@ / These options have no effect in read-only configuration (FF_FS_READONLY = 1). */ +#define FF_FS_CRTIME 0 +/* This option enables(1)/disables(0) the timestamp of the file created. When +/ set 1, the file created time is available in FILINFO structure. */ + + #define FF_FS_NOFSINFO 0 -/* If you need to know correct free space on the FAT32 volume, set bit 0 of this -/ option, and f_getfree() at the first time after volume mount will force +/* If you need to know the correct free space on the FAT32 volume, set bit 0 of +/ this option, and f_getfree() on the first time after volume mount will force / a full FAT scan. Bit 1 controls the use of last allocated cluster number. / / bit0=0: Use free cluster count in the FSINFO if available.