History: fs_fat

This page describes all changes made to the fs_fat package, FAT File System, since its release.


10.7 (2021-04-16, 11:15):

  • Bugfix: fail-safe FAT could become non fail-safe (file could get corrupted) when underlying media does not write sectors in the requested order (e.g. with media driver cache, in "r+" mode and when reset or power failure occurred).
  • Bugfix: in fail-safe mode lost clusters could develop if power failure occurred during f_open() in "r+" mode with FAT cache enabled (write order of the old and new clusters could have been reversed).

10.6 (2021-03-12, 14:40):

  • Number of files with long file names having same leading characters in their file names converted to short names is increased to 100000.
  • Eliminated more C16x Compiler warnings.
  • f_close() did not update directory entries on the media when volume was in safe mode, but file was opened in non-safe mode. The error produced a zero-size file after reset or f_delvolume()/f_initvolume().
  • PSP_ASSERT may have detected false positive error in safe mode when USE_MALLOC=1.

10.5 (2021-03-08, 08:40):

  • Eliminated C16x Compiler warnings.

10.4 (2021-03-05, 13:24):

  • It uses media driver's copy sector function (F_IOCTL_MSG_COPY_SECTOR) in safe mode if corresponding IOCTL call is supported.
  • Bugfix: f_truncate() may have caused buffer indexing error in safe mode.

10.3 (2021-02-26, 13:04):

  • PSP_ASSERT may have detected false positive error if file is written in safe mode and error occurred during write (e.g. because card removed).

10.2 (2021-02-12, 08:22):

  • Compiler warnings were eliminated.

10.1 (2021-01-21, 14:26):

  • Added AES-GCM encryption support.
  • Changed f_open_enc() API: input parameters are the type of encryption to be used and the cypher data structure (t_enc_cypher_data from api_enc.h), instead of key and init vector. This way any encryption method can be added in the future.
  • Added f_get_volume_info() to obtain volume information (bytes/sector, bytes/cluster, first sector of the volume, number of sectors and type of the media).
  • Removed f_get_cluster_size() (replaced by f_get_volume_info()).
  • Optimized f_write(): it tries to find consecutive clusters if writing to more than one cluster.
  • Optimized f_seek(): it uses seek position optimization in mode 'r+' in safe mode till the first write. After that the safe log optimized seek is used.

9.20 (2020-12-10, 09:05):

  • Deferring creation of safe log files in case of open mode 'r+':  log files are created on first write instead of writing them at file open.

9.19 (2020-11-26, 15:03):

  • Drive becomes read-only in case of write error (if BAD_BLOCK_HANDLING is disabled).
  • Bugfix: if f_initvolume() returns F_ERR_REPAIRNEEDED, other functions might have returned F_ERR_UNUSABLE.

9.18 (2020-10-09, 11:33):

  • Added f_get_volume_state(): volume's dirty bit can be read. Older method (FAT index #1) and newer method (boot record) is also taken into consideration.
  • f_findfirst() and f_findnext() use directory cache if available.
  • f_seek() optimized - effective if file is opened for writing in safe mode.
  • Fixed f_initvolume(): it could modify media if F_SAFE_AUTO_REPAIR is 0.

9.17 (2020-09-14, 12:34):

  • Volume buffer was not allocated when USE_MALLOC was 1.
  • Optimized opening of existing file in mode "r+" in safe mode.
  • File offset variable can be configured by user via USE_LONG_LONG_OFFSET macro (applies to f_filelength(), f_wfilelength(), f_tell() and f_seek()).
  • Optimized finding of free cluster for FAT12/FAT16.

9.16 (2020-08-07, 12:16):

  • FAT1 and FAT2 could differ if f_repair() or f_initvolume() is used after power failure or unexpected media removal.
  • f_delvolume() may stuck in an endless loop if F_MAXFILES is greater than 84 in safe mode.
  • PSP_ASSERT() could detect a false positive error in f_close() when the media was removed and getstatus() function is not implemented.

9.15 (2020-07-30, 12:11):

  • Introduced volume buffer. It can speed up seek/truncate beyond file size.
  • Removed F_MAXSNAME, F_MAXSEXT and F_DEF_SECTOR_SIZE from configuration as they are constant values.
  • Eliminated compiler warning.

9.14 (2020-07-28, 17:58):

  • fn_rename() created absolute pathname with two path separators ('//') at the beginning if the file was in the root directory. This could lead to a failure in renaming when FN_MAXLNAME was smaller by one than FN_MAXPATHNAME.

9.13 (2020-07-22, 10:56):

  • f_stat() can handle root directory as well. Before this it returned an error.

9.12 (2020-07-14, 17:00):

  • Warnings removed

9.11 (2020-07-09, 10:49):

  • PSP_ASSERT() could detect a false positive error in f_close() when the media was removed.
  • Eliminated compiler warning.

9.10 (2020-07-06, 10:35):

  • f_repair() returns error if no repair is needed (F_SAFE_AUTO_REPAIR=0).

9.9 (2020-06-23, 10:55):

  • Optimized f_write(): it could allocate and copy cluster needlessly during append to a file in safe mode.

9.8 (2020-05-27, 13:50):

  • Added f_open_wenc(): it can open encrypted file with Unicode path.
  • Bugfix: f_mkdir() could create cross-linked directory if only one free cluster left on the media.
  • Bugfix: f_mkdir(), f_open(), f_open_enc(), f_open_nonsafe(), f_rename(), f_move() may return F_ERR_INVALIDSECTOR when cluster size is 512 bytes, directory was almost full and filename is longer than 208 bytes.
  • Bugfix: f_write() left file handle in erroneous state when media get full. It was necessary to re-open the file if space was made on the media.
  • Bugfix: f_getfreespace() could return false information if error occurred during file/directory creation or removal between two f_getfreespace() calls. Free space could underrun.
  • Bugfix: bad block handling could cause NULL pointer de-reference. (BAD_BLOCK_HANDLING=1 and SAFEFAT=0).
  • Bugfix: FAT bitfield handling was fixed as it calculated free space wrongly. Wrong calculation resulted that few clusters cannot be allocated when media was almost full (when FATBITFIELD_ENABLE=1).
  • Bugfix: disk usage could calculate wrongly the size of root directory if FAT32 and 512 bytes cluster was used with long filenames.
  • Volume is made read-only if FAT writing fails to prevent creation of cross-chained clusters.

9.7 (2020-05-12, 11:21):

  • The following functions can detect endless FAT chains and return F_ERR_CHECKNEEDED instead of running forever: f_disk_usage(),  f_wdisk_usage(), f_seteof(), f_open(), f_open_nonsafe(), f_open_enc(),  f_wopen(), f_wopen_nonsafe(), f_delete(), f_wdelete(), f_deletecontent(), f_wdeletecontent(), f_rmdir(), f_wrmdir(), f_ftruncate(), f_truncate(), f_wtruncate(), f_volume_clean().
  • Changes to make compatible with fs_fat_checkdisk().

9.6 (2020-04-21, 13:30):

  • Unique file ID can be retrieved with f_stat() and f_fstat().
  • Bugfix: f_seek() could not seek to end of file if it was at cluster boundary.
  • Bugfix: f_open() could de-reference NULL pointer of open mode.
  • Support for FMW added (FAT_FMW_ENABLE in config_fat.h, enables the option to allow opening the same file multiple times for write).

9.5 (2020-04-08, 10:20):

  • Compiler error that comes with some toolchains was eliminated (if F_DIR_WALK_SUPPORT is set to zero in config_fat.h then F_VOLUME_CLEAN_SUPPORT was not defined).

9.4 (2020-04-03, 10:07):

  • Compiler warnings were eliminated.

9.3 (2020-03-23, 09:26):

  • SafeFAT: clusters of safe logs allocated from different place of volume to prevent fragmentation of clusters.
  • Volume clean function does not use 64 bit variable anymore.

9.2 (2020-03-02, 12:23):

  • Eliminated compiler error that occurred when CAPI was used with F_VOLUME_CLEAN_SUPPORT enabled.

9.1 (2020-02-20, 10:01):

  • Implemented volume clean function.
  • Disk usage function now uses two 32 bit variables instead of one 64 bit variable.

8.53 (2019-12-03, 14:29):

  • Static analysis issues eliminated.

8.52 (2019-11-28, 15:02):

  • Compiler warnings got eliminated.

8.51 (2019-10-30, 10:50):

  • IOCTL flush is called to prevent data loss.

8.50 (2019-10-18, 15:54):

  • Static analysis issues eliminated.

8.49 (2019-09-17, 16:22):

  • BAD_BLOCK_HANDLING configuration option added to enable or disable the bad block handling mechanism.
  • Function added to replace a bad cluster in the seekpos[] array to a new good one. Only used in bad block handling.

8.48 (2019-09-13, 12:00):

  • Eliminated C++ compiler errors.

8.47 (2019-09-09, 13:00):

  • Eliminated static analysis issues.

8.46 (2019-08-13, 16:50):

  • Added F_SAFE_AUTO_REPAIR configuration option. If this is set to 0 and repair is needed f_initvolume() initializes file system as read-only.
  • Added f_repair() to repair SafeFAT, and to enable file system read/write again.

8.45 (2019-06-25, 10:34):

  • Encrypted mode didn't work correctly after using f_flush(), read data could have been wrong.
  • f_seek() performance improved for encrypted files (originally all data sectors were read up to the seek position, now only one is).
  • Multi-sector read didn't work for encrypted files where the read size was greater than 64KB.

8.44 (2019-04-05, 17:09):

  • Encrypted data bigger than a sector was read incorrectly.
  • Disabled r+ file opening in encrypted mode (not possible to update encrypted data inside the file as it will ruin the keys).

8.43 (2019-02-12, 14:47):

  • Fixed bug that allowed opening of a file with short name plus at least one character when F_LONGFILENAME, HCC_UNICODE and  F_SHIFT_JIS_SUPPORT are enabled.

8.42 (2018-11-05, 12:00):

  • Enabled file opening for w and r+ in encrypted mode.

8.41 (2018-09-25, 7:00):

  • Applied fixes of CERT compliance review findings (boundary checks, out-of-boundary access of arrays).

8.40r2 (2018-08-29, 18:08):

  • Document HTML link added to the documentation folder.
  • History and document files renamed to the package name.

8.40 (2018-07-18, 10:01):

  • Fixed handling of FN_MAXPATHNAME. It could not handle full length  (FN_MAXPATHNAME) path when F_FILE_CHANGED_EVENT is enabled.

8.39 (2018-07-17, 14:50):

Functions could not work with maximum (FN_MAXPATHNAME) length arguments when Unicode was enabled.

8.38 (2018-07-13, 09:46):

  • f_rename() and f_move() could return F_ERR_NOTFOUND when long filenames directory cache and SafeFAT were used at the same time.

8.37 (2018-06-09, 17:49):

  • Shift JIS: fn_getlabel() did not set Japanese Shift JIS multibyte characters correctly.
  • Shift JIS: Every other character was skipped when file name was created with Japanese hankaku kana(single byte 0xA1-0xDF) characters.
  • Shift JIS: Some of translation record in fat_shjis.c was missing for cp932 to Unicode conversions.

8.36 (2018-06-05, 8:50):

  • Fixed version check in config_fat.c template file.

8.36 (2018-05-24, 19:22):

  • Fixed version cross check to ensure that the right version of media driver (media_drv_base) is used.

8.35 (2018-05-10, 12:02):

  • Implemented f_dir_walk() and f_disk_usage() functions.

8.34 (2018-05-03, 12:51):

  • IOCTL flush is called when a file is closed or flushed to prevent data loss.

8.33 (2018-04-13, 17:47):

  • Writing to files opened in a/a+ mode could cause unnecessary read operations, possibly increasing write time significantly.

8.32 (2018-03-20, 06:52):

  • f_open() could lead to unusable file system (until restart) when SafeFAT was used in full root directory of FAT12 or FAT16 file system.

8.31 (2018-02-22, 08:31):

  • f_rename() and f_move() could produce extra file entries during operation when long filenames are used.

8.30 (2018-01-19, 12:37):

  • Eliminated compiler warning.

8.29 (2018-01-05, 09:08):

  • f_rename() could return error F_ERR_NOTFOUND when long filenames, directory cache, and SafeFAT were used at the same time.

8.28 (2017-11-30, 09:19):

  • File name length of 254 was not accepted with long filenames enabled.

8.27 (2017-11-24, 15:53):

  • Files opened first in "r" mode can now be opened in "r+" mode.

8.26 (2017-10-09, 09:33):

  • Compiler warnings were eliminated.

8.25 (2017-09-26, 16:46):

  • Compiler warnings eliminated.

8.24 (2017-09-01, 16:02):

  • EEM global init function not called from FAT initialization.
  • ENC key and block size separated (as a result it can be used with AES-128, AES-192 and AES-256).

8.23 (2017-07-19, 12:35):

  • Static analyzer (CodeSonar) warnings were eliminated.


  • Supports 64-bit environments.


  • The system previously could write uninitialized data to boot record during formatting: it now clears the sector buffer properly before writing.


  • File encryption support added (in r, a, a+ modes).


  • psp_types.h is included instead of stdint.h.


  • Reopening "r+" files in "r" mode is allowed.


  • f_findfirst() complex search patterns searching for and long filenames has been improved.


  • SafeFAT: inline function modified to non-inline.


  • SafeFAT: f_flush() could corrupt the new file in some rare conditions (when the size of the cluster chain of the destination file was multiple of clusters).


  • Warnings eliminated.


  • Writing to "a", "a+", "w", "w+" files and concurrent access of these files and "r" files are handled identically as in standard C library.


  • Buffer indexing error was fixed in fn_setvolname().
  • SafeFAT: cf_create() returns error if it finds files with the same name in $$SAFE$$ folder.
  • SafeFAT: volume becomes read-only if safe_docommands() failed.
  • SafeFAT: volume remains not initialized if safe_poweron() failed during f_initvolume().


  • f_createpartition_align() introduced, it can create new partitions aligned to given sector boundaries.


  • f_rename() correctly renames files in subfolders.


f_releaseFS() frees up all memory allocated by f_enterFS().


  • SafeFAT: issue fixed with f_move() and other filename manipulating API functions not being safe when long filenames are used.
  • SafeFAT: f_close() won't call psp_free() twice on file handles when FAT is compiled with USE_MALLOC and the media is removed just before the f_close() call.
  • SafeFAT: f_seteof() correctly frees up clusters in SAFEFAT mode.


  • Newly introduced F_CLUSTERBUFFER option allows using a dedicated cluster buffer in SAFEFAT mode to speed up overwriting big files.


  • fm_open_pos() internal function can be used by to start searching for the filename at a given position.


  • In SAFEFAT mode f_delvolume() sets the sizes of system files in $$SAFE$$ folder to a valid value which makes Windows CHKDSK pass.


  • FAT returns F_ERR_NOTFORMATTED instead of F_ERR_NOTSUPPSECTORSIZE when trying to initialize a medium that contains a valid FAT name and signature but invalid volume information. Master Boot records can contain such information on medias formatted to exFAT for example.


  • FAT can now properly mount volumes on a partitioned media created by Windows. Problem occurred if only the volume sector area was given to the file system and not the whole media (including partition table).


  • In case of success fn_seek() and fn_rewind() did not clear global errno leaving possible error code in it.


  • When USE_MALLOC is set number of volumes and tasks is limited only by the available memory. Maximum number of files is 2048 but is also limited by the available memory.
  • FAT now requires OAL_BASE and an OAL_OS package.
  • Works with FUSE or POSIX-like systems with a non-polling OAL and FAT_MAXTASK set to 1.


  • f_delvolume() could incorrectly close file handles on other volume.
  • Short version of a SHIFT_JIS long filename is handled properly.
  • In case the media is write protected the first API call that tries to write incorrectly returned F_ERR_ONDRIVE instead of F_ERR_WRITEPROTECT.
  • f_findfirst()/f_findnext() could return incorrect content in case of file/directory creation/deletion.
  • F_ERR_CARDCHANGED error code introduced.
  • Warnings removed.


  • Static configuration didn't work if FAT_MAXVOLUME was greater than 2.
  • Seek/truncate beyond end of file didn't work correctly on Safe FAT volumes.

 - compiler warnings eliminated if F_SHIFT_JIS_SUPPORT is enabled.
 - compiler warnings eliminated.

 - directory handling fixed with long file names enabled on FAT12/16 volumes (F_ERR_INVALIDSECTOR could have been returned if the file system was using directories created with another FAT file system).

 - F_MAXFILES can now be set to the real requirement, before some functions (mainly write functions - mkdir, open for write, etc.) didn't work correctly if all files were used.

 - SHIFT JIS character support added.

 - f_rename() restored in order for correct parameter usage (f_move() was used but the 2nd parameter requires path name while f_rename() does not).

 - compiler warnings eliminated.

 - volume-based configuration introduced, config_fat.h contains settings for up to 4 different volumes.
 - fs_init(), fs_start(), fs_stop(), fs_delete() added.

 - Warning removed if safe FAT is used, NONSAFEFAT is not set in config_fat.h and long file names are enabled.

 - possible warnings (using uninitialized variables) eliminated.

 - possible static analysis warnings fixed, init.c and init.h eliminated.

 - file operations don't report error when F_DELETE_CONTENT is used and the actual media driver doesn't implement the necessary ioctl functions

 - support for sector sizes which aren't the multiple of 32 bytes (e.g. 528).

 - F_MAXSEEKPOS will be disabled for volumes with non power of two sector size.

 - psp_malloc() will be used for memory allocation, f_init() doesn't require the pf_malloc argument any more.

 - non-configuration parts removed from config_fat.h.

 - f_fstat() added, which returns the stat based on file handle.

 - warning removed

 - F_VOLNAME_SUPPORT added. f_setvolname(), f_getvolname() to set and query the name of a volume. In file operation the absolute pathname may contain either the drive letter or the volume name (eg. "volname:/path/filename").

 - F_FILE_CHANGED_EVENT fixed, it works with HCC_UNICODE too

 - mount count reworked. f_close() also increments p_filesystem→drvbldnum, each file operation checks again f->file.reference after _f_getvolume(). This prevents file operations from working with unexpectedly changed file handles (if the file would have been reopened in another task)

 - f_tell() returns -1 instead of F_ERR_TASKNOTFOUND in case the task was not entered with f_enterFS().

 - f_get_volume_count() and f_get_volume_list() count only successfully mounted FAT volumes.

 - USE_MALLOC now allocates space for all the data structures

 - f_open() and f_truncate() fixed for NON-SAFE volumes when SAFEFAT is defined

 - warnings removed

 - f_createpartition() will return error if the 2nd or any succeeding partition wouldn't fit onto the media

 - f_dotest() passes now with F_LONGFILENAME and without DIRCACHE_ENABLE

 - f_initvolumepartition() and f_getpartition() try to find a valid MBR first and fall back to detect FAT VBR next

 - _f_addentry() in fat_lfn.c uses the plain short-file-name without tilde if it fits into the 8+3 format.

 - _f_drvgetphy(): presence of driver->getstatus is not needed

 - 'bootable' field added to F_PARTITION. f_getpartition() returns the active state of a partition in this field, f_createpartition() uses this field to set/clear the active flag of the new partition

 - safe_poweron() now flushes FAT after f_format() or during f_initvolume() to prevent cross-linking when the filesystem is also used in NONSAFE mode.

 - FATBITFIELD bug fixed

 - f_flush_filebuffer() added. It writes out the data buffer of the selected file. Works only with files which were opened in non-safe mode and which are not opened multiple times.

 - FN_SEEK_NOWRITE flag added. Old FN_SEEK... constants can be combined with this flag to seek beyond EOF without writing out zeros to the file.

 - #if 0 removed from fat_lfn.c.

 - warnings removed.

 - debug.h removed.

 - warnings fixed.

 - default maximum sector size changed to 512 in the config file.

 - added fix for "undefined macro used in expression" warning in fat.h.

 - psp_time renamed to psp_rtc.

 - only affects the safe module: when flushing a file it will only copy the cluster chain from the point where it changed, as a result there will be much faster flush execution for big files.

 - time/date generation fixed.

 - if media was unplugged during delvolume() the system became unusable because a mutex was not released.
 - oal_task_id_t used instead of long for task ID.
 - FAT test package separated.

 - cleanup.

 - made CAPI compatible.
 - psp_getcurrenttimedate() used.
 - psp_getrand() used

 - f_set_format_progress() introduced to avoid the need to define f_format_progress() function if not required.

 - f_rename() defined to f_move() to keep backward-compatibility.

 - warnings removed.

 - version check added to all files in the module.

 - Initial review.