diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..467e2a2 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,24 @@ +FatFs License + +FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files. + +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem Module Rx.xx / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 20xx, 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 +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/----------------------------------------------------------------------------*/ + +Therefore FatFs license is one of the BSD-style licenses but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, does not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses including GNU GPL. When you redistribute the FatFs source code with any changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license. diff --git a/documents/00index_e.html b/documents/00index_e.html index bcc499e..9ada28b 100644 --- a/documents/00index_e.html +++ b/documents/00index_e.html @@ -24,7 +24,7 @@
  • Very small footprint for program code and work area.
  • Various configuration options to support for: -

    The fast seek function 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 function is enabled when the member cltbl in the file object is not NULL. The CLMT must be created into the DWORD array prior to use the fast seek function. 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 first item and call the f_lseek function with ofs = CREATE_LINKMAP. After the function succeeded and CLMT is created, 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 first item of the array. The number of items to be used is (number of the file fragments + 1) * 2. For example, when the file is fragmented in 5, 12 items in the array will be used. If the function failed with FR_NOT_ENOUGH_CORE, the given array size is insufficient for the file.

    +

    The fast seek function 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 enabled when the member cltbl in the file object is not NULL. The CLMT must be created into the DWORD array prior to use the fast seek function. 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 first item and call the f_lseek function with ofs = CREATE_LINKMAP. After the function succeeded and CLMT is created, 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 first item of the array. The number of items to be used is (number of the file fragments + 1) * 2. For example, when the file is fragmented in 5, 12 items in the array will be used. If the function failed with FR_NOT_ENOUGH_CORE, the given array size is insufficient for the file.

    QuickInfo

    -

    Available when FF_FS_MINIMIZE <= 2. To use fast seek function, FF_USE_FASTSEEK needs to be set 1.

    +

    Available when FF_FS_MINIMIZE <= 2. To use fast seek function, FF_USE_FASTSEEK needs to be set 1 to enable this feature.

    @@ -91,13 +91,13 @@ FRESULT f_lseek ( res = f_open(fp, recfile, FA_CREATE_NEW | FA_WRITE); /* Create a file */ res = f_lseek(fp, PRE_SIZE); /* Expand file size (cluster pre-allocation) */ - if (res || f_tell(fp) != PRE_SIZE) ... /* Check if the file has been expanded */ + if (res || f_tell(fp) != PRE_SIZE) ... /* Check if the file has been expanded successfly */ res = f_lseek(fp, DATA_START); /* Record data stream WITHOUT cluster allocation delay */ ... /* Write operation should be aligned to sector boundary to optimize the write throughput */ res = f_truncate(fp); /* Truncate unused area */ - res = f_lseek(fp, 0); /* Put file header */ + res = f_lseek(fp, 0); /* Set file header */ ... res = f_close(fp); diff --git a/documents/doc/mkfs.html b/documents/doc/mkfs.html index a74c07b..4ea6937 100644 --- a/documents/doc/mkfs.html +++ b/documents/doc/mkfs.html @@ -59,9 +59,9 @@ FRESULT f_mkfs (

    Description

    The FAT sub-type, FAT12/FAT16/FAT32, of FAT volume except exFAT is determined by only number of clusters on the volume and nothing else, according to the FAT specification issued by Microsoft. Thus the FAT sub-type of created volume depends on the volume size and the cluster size. In case of the combination of FAT type and cluter size specified by argument cannot be valid on the volume, the function will fail with FR_MKFS_ABORTED. The minimum drive size is 128 sectors with FM_SFD option.

    The allocation unit, also called 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 as the size of allocation unit. Therefore the size of allocation unit is a trade-off between space efficiency and performance. For the large storages in GB order, 32768 bytes or larger (this is automatically selected by default) is recommended for most case unless extremely many small files are created on a volume.

    -

    There are two disk partitioning formats, FDISK and SFD. The 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 on the MBR (maser boot record, the first sector of the physical drive). The SFD (super-floppy disk) format is non-partitioned disk format. The FAT volume starts at the first sector of the physical drive without any disk partitioning. It is usually used for floppy disk, optical disk and most super-floppy media. Some systems support only either one of the two disk formats and the other is not supported.

    -

    When the logical drive to be formatted is bound to a physical drive and FM_SFD is not specified, a primary partition occupies whole drive space is created and then the FAT volume is created in it. When FM_SFD is specified, the FAT volume occupies from the first sector of the physical drive is created without partitioning.

    -

    When the logical drive to be formatted is bound to a specific partition (1-4) by support of multiple partition (FF_MULTI_PARTITION == 1) the FAT volume is created into the partition and FM_SFD flag is ignored. The physical drive needs to be partitioned with f_fdisk function or any other partitioning tools prior to create the FAT volume with this function.

    +

    There are three disk partitioning formats, FDISK, SFD and GPT. The 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 on the MBR (maser boot record, the first sector of the physical drive). The SFD (super-floppy disk) is non-partitioned disk format. The FAT volume starts at the first sector of the physical drive without any disk partitioning. It is usually used for floppy disk, optical disk and most super-floppy media. Some systems support only either one of the two disk formats and the other is not supported. The GPT (GUID Partition Table) is a newly defined format for large storage devices. FatFs does not support the storages with GPT.

    +

    When the logical drive to be formatted is bound to a physical drive and FM_SFD is not specified, a primary partition occupies whole drive space is created in FDISK format, and then the FAT volume is created in the partition. When FM_SFD is specified, the FAT volume occupies from the first sector of the physical drive is created in SFD format.

    +

    When the logical drive to be formatted is bound to a specific partition (1-4) by support of multiple partition (FF_MULTI_PARTITION == 1), the FAT volume is created on the partition and FM_SFD flag is ignored. The physical drive needs to be partitioned with f_fdisk function or any other partitioning tools prior to create the FAT volume with this function.

    diff --git a/documents/doc/mount.html b/documents/doc/mount.html index 3f2acce..3f70ef7 100644 --- a/documents/doc/mount.html +++ b/documents/doc/mount.html @@ -50,7 +50,7 @@ FRESULT f_mount (

    Description

    -

    FatFs needs work area (filesystem object) for each logical drives (FAT volumes). Prior to perform file/directory operations, a filesystem object needs to be registered with f_mount function to the logical drive. The file/directory API functions get ready to work after this procedure. If there is any open object of file or directory on the logical drive, the object will be invalidated by this function.

    +

    FatFs requires work area (filesystem object) for each logical drives (FAT volumes). Prior to perform file/directory operations, a filesystem object needs to be registered with f_mount function to the logical drive. The file/directory API functions get ready to work after this procedure. If there is any open object of file or directory on the logical drive, the object will be invalidated by this function.

    The f_mount function registers/unregisters a filesystem object to the FatFs module as follows:

    1. Determines the logical drive which specified by path.
    2. @@ -58,13 +58,14 @@ FRESULT f_mount (
    3. Clears and registers the new work area to the volume if fs is not NULL.
    4. Performs volume mount process to the volume if forced mounting is specified.
    -

    If forced mounting is not specified (opt = 0), this function always succeeds regardless of the physical drive status. It only clears (de-initializes) the given work area and registers its address to the internal table and no activity of the physical drive in this function. To unregister the work area, specify a NULL to the fs, and then the work area can be discarded. The volume mount processes, initialize the corresponding physical drive, find the FAT volume in it and then initialize the work area, is performed in the subsequent file/directory functions when either of following conditions is true.

    +

    If forced mounting is not specified (opt = 0), this function always succeeds regardless of the physical drive status. It only clears (de-initializes) the given work area and registers its address to the internal table and no activity of the physical drive in this function. The volume mount process will be attempted on subsequent file/directroy function if the filesystem object is not initialized. (delayed mounting) The volume mount processes, initialize the corresponding physical drive, find the FAT volume in it and then initialize the work area, is performed in the subsequent file/directory functions when either of following conditions is true.

    • Filesystem object has not been initialized. It is de-initialized by f_mount function.
    • Physical drive is not initialized. It is de-initialized by system reset or media removal.
    -

    If the function with forced mounting (opt = 1) failed, it means that the filesystem object has been registered successfully but the volume is currently not ready to work. The volume mount process will be attempted at subsequent file/directroy functions if the filesystem object is not initialized. (delayed mounting)

    +

    If the function with forced mounting (opt = 1) failed with FR_NOT_READY, it means that the filesystem object has been registered successfully but the volume is currently not ready to work. The volume mount process will be attempted on subsequent file/directroy function.

    If implementation of the disk I/O layer lacks asynchronous media change detection, application program needs to perform f_mount function after each media change to force cleared the filesystem object.

    +

    To unregister the work area, specify a NULL to the fs, and then the work area can be discarded.

    diff --git a/documents/doc/open.html b/documents/doc/open.html index 1dd81d8..c5dd7c5 100644 --- a/documents/doc/open.html +++ b/documents/doc/open.html @@ -43,18 +43,17 @@ FRESULT f_open ( FA_OPEN_APPENDSame as FA_OPEN_ALWAYS except the read/write pointer is set end of the file. Mode flags of POSIX fopen() corresponds to FatFs mode flags as follows:
    - +
    - - - - - - - - + + + + + + + +
    POSIXFatFs
    "r"FA_READ
    "r+"FA_READ | FA_WRITE
    "w"FA_CREATE_ALWAYS | FA_WRITE
    "w+"FA_CREATE_ALWAYS | FA_WRITE | FA_READ
    "a"FA_OPEN_APPEND | FA_WRITE
    "a+"FA_OPEN_APPEND | FA_WRITE | FA_READ
    "x"*1FA_CREATE_NEW | FA_WRITE
    "x+"*1FA_CREATE_NEW | FA_WRITE | FA_READ
    "r"FA_READ
    "r+"FA_READ | FA_WRITE
    "w"FA_CREATE_ALWAYS | FA_WRITE
    "w+"FA_CREATE_ALWAYS | FA_WRITE | FA_READ
    "a"FA_OPEN_APPEND | FA_WRITE
    "a+"FA_OPEN_APPEND | FA_WRITE | FA_READ
    "wx"FA_CREATE_NEW | FA_WRITE
    "w+x"FA_CREATE_NEW | FA_WRITE | FA_READ
    -*1: glibc extension
    diff --git a/documents/doc/printf.html b/documents/doc/printf.html index e345c23..82be70c 100644 --- a/documents/doc/printf.html +++ b/documents/doc/printf.html @@ -54,13 +54,13 @@ int f_printf (
    width
    Minimum width of the field, 1-99 or *. If the width of generated string is less than the specified value, rest field is padded with white spaces or zeros. An * specifies the value comes from an argument in int type.
    type
    c s d u o x b and prefix l specify type of the argument, character, string, signed integer in decimal, unsigned integer in decimal, unsigned integer in octal, unsigned integer in hexdecimal and unsigned integer in binary respectively. If sizeof (long) is greater than sizeof (int) (this is typical of 8/16-bit systems), a prefix l needs to be explicitly specified for long integer argument. These characters except for x are case insensitive.
    -

    When FatFs is configured for Unicode API (FF_LFN_UNICODE >= 1), character encoding on the string fuctions, f_putc, f_puts, f_printf and f_gets function, is also switched to Unicode. The Unicode characters in multiple encoding unit, such as surrogate pair and multi-byte sequence, should not be divided into two function calls, or the character will be lost. The character encoding on the file to be written via this function is selected by FF_STRF_ENCODE option. If the character encoding on the file differs from that on the API, it is converted in this function. In this case, input characters with wrong encoding or invalid for the output will be lost.

    +

    When FatFs is configured for Unicode API (FF_LFN_UNICODE >= 1), character encoding on the string fuctions, f_putc, f_puts, f_printf and f_gets function, is also switched to Unicode. The Unicode characters in multiple encoding unit, such as surrogate pair and multi-byte sequence, should not be divided into two function calls, or the character will be lost. The character encoding on the file to be written via this function is selected by FF_STRF_ENCODE. The characters with wrong encoding or invalid for the output encoding will be lost.

    QuickInfo

    -

    This is a wrapper function of f_write function. Available when FF_FS_READONLY == 0 and FF_USE_STRFUNC >= 1. When it is set to 2, '\n's contained in the output are converted to '\r'+'\n' each.

    +

    This is a wrapper function of f_write function. Available when FF_FS_READONLY == 0 and FF_USE_STRFUNC >= 1. When FF_USE_STRFUNC == 2, '\n's in the generated string are written as '\r'+'\n' each.

    diff --git a/documents/doc/putc.html b/documents/doc/putc.html index b7cd558..2e9fa99 100644 --- a/documents/doc/putc.html +++ b/documents/doc/putc.html @@ -16,7 +16,7 @@

    The f_putc funciton puts a character to the file.

     int f_putc (
    -  TCHAR chr,  /* [IN] A character to put */
    +  TCHAR chr,  /* [IN] A character to write */
       FIL* fp     /* [IN] File object */
     );
     
    @@ -26,7 +26,7 @@ int f_putc (

    Parameters

    chr
    -
    A character to be put.
    +
    A character to write.
    fp
    Pointer to the open file object structuer.
    @@ -41,12 +41,12 @@ int f_putc (

    Description

    -

    When FatFs is configured for Unicode API (FF_LFN_UNICODE >= 1), character encoding on the string fuctions, f_putc, f_puts, f_printf and f_gets function, is also switched to Unicode. The character encoding on the file to be written via those functions is selected by FF_STRF_ENCODE option. The Unicode characters in multiple encoding unit, such as surrogate pair and multi-byte sequence, cannot be written by this function.

    +

    When FatFs is configured for Unicode API (FF_LFN_UNICODE >= 1), character encoding on the string fuctions, f_putc, f_puts, f_printf and f_gets function, is also switched to Unicode. The character encoding on the file to be read/written via those functions is selected by FF_STRF_ENCODE. The Unicode characters in multiple encoding unit, such as surrogate pair and multi-byte sequence, cannot be written with this function.

    QuickInfo

    -

    This is a wrapper function of f_write function. Available when FF_FS_READONLY == 0 and FF_USE_STRFUNC is 1 or 2. When it is set to 2, a '\n' is converted to '\r'+'\n'.

    +

    This is a wrapper function of f_write function. Available when FF_FS_READONLY == 0 and FF_USE_STRFUNC >= 1. When FF_USE_STRFUNC == 2, a '\n' is output as '\r'+'\n'.

    diff --git a/documents/doc/puts.html b/documents/doc/puts.html index a644419..8f2a7ce 100644 --- a/documents/doc/puts.html +++ b/documents/doc/puts.html @@ -41,13 +41,13 @@ int f_puts (

    Description

    -

    When FatFs is configured for Unicode API (FF_LFN_UNICODE >= 1), character encoding on the string fuctions, f_putc, f_puts, f_printf and f_gets function, is also switched to Unicode. The input Unicode characters in multiple encoding unit, such as surrogate pair and multi-byte sequence, should not be divided into two function calls, or the character will be lost. The character encoding on the file to be written via this functions is selected by FF_STRF_ENCODE option. If the character encoding on the file differs from that on the API, it is converted in this function. In this case, input characters with wrong encoding or invalid for the output will be lost.

    +

    When FatFs is configured for Unicode API (FF_LFN_UNICODE >= 1), character encoding on the string fuctions, f_putc, f_puts, f_printf and f_gets function, is also switched to Unicode. The input Unicode characters in multiple encoding unit, such as surrogate pair and multi-byte sequence, should not be divided into two function calls, or the character will be lost. The character encoding on the file to be written via this functions is selected by FF_STRF_ENCODE. The characters with wrong encoding or invalid for the output encoding will be lost.

    QuickInfo

    -

    This is a wrapper function of f_write function. Available when FF_FS_READONLY == 0 and FF_USE_STRFUNC is 1 or 2. When it is set to 2, '\n's contained in the string are converted to '\r'+'\n'.

    +

    This is a wrapper function of f_write function. Available when FF_FS_READONLY == 0 and FF_USE_STRFUNC >= 1. When FF_USE_STRFUNC == 2, '\n's contained in the input string are output as '\r'+'\n' each.

    diff --git a/documents/doc/rc.html b/documents/doc/rc.html index 00a7556..4b2ce43 100644 --- a/documents/doc/rc.html +++ b/documents/doc/rc.html @@ -19,7 +19,7 @@
    The function succeeded.
    FR_DISK_ERR
    -
    The lower layer, disk_read, disk_write or disk_ioctl function, reported that an unrecoverable hard error occured.
    Note that if once this error occured at any operation to an open file, the file object is aborted and all operations to the file except for close will be rejected.
    +
    The lower layer, disk_read, disk_write or disk_ioctl function, reported that an unrecoverable hard error occured.
    Note that if once this error occured at any operation to an open file, the file object is aborted and any operations to the file except for close will be rejected.
    FR_INT_ERR
    Assertion failed. An insanity is detected in the internal process. One of the following possibilities is suspected. @@ -27,6 +27,7 @@
  • Work area (file system object, file object or etc...) has been broken by stack overflow or any other tasks. This is the reason in most case.
  • There is an error of the FAT structure on the volume.
  • There is a bug in the FatFs module itself.
  • +
  • Wrong lower layer implementation.
  • Note that if once this error occured at any operation to an open file, the file object is aborted and all operations to the file except for close will be rejected.
    @@ -35,9 +36,9 @@ Note that if once this error occured at any operation to an open file, the file
    The lower layer, disk_initialize function, reported that the storage device could not be got ready to work. One of the following possibilities is suspected.
    @@ -92,14 +93,13 @@ Note that if once this error occured at any operation to an open file, the file
    Work area for the logical drive has not been registered by f_mount function.
    FR_NO_FILESYSTEM
    -
    There is no valid FAT volume on the drive.
    +
    There is no valid FAT volume on the drive or wrong lower layer implementation.
    FR_MKFS_ABORTED
    The f_mkfs function aborted before start in format due to a reason as follows:
    diff --git a/documents/doc/read.html b/documents/doc/read.html index dfa883a..12c57cd 100644 --- a/documents/doc/read.html +++ b/documents/doc/read.html @@ -34,7 +34,7 @@ FRESULT f_read (
    btr
    Number of bytes to read in range of UINT type.
    br
    -
    Pointer to the UINT variable to return number of bytes read. This value is always valid after the function call regardless of the return value.
    +
    Pointer to the UINT variable to return number of bytes read. This value is always valid after the function call regardless of the function return code.
    diff --git a/documents/doc/setlabel.html b/documents/doc/setlabel.html index d596469..2ec5d42 100644 --- a/documents/doc/setlabel.html +++ b/documents/doc/setlabel.html @@ -49,12 +49,13 @@ FRESULT f_setlabel (

    Description

    -

    When the string has a drive number, the volume label will be set to the volume specified by the drive number. If not, the volume label will be set to the default drive. If length of the given volume label is zero, the volume label on the volume will be removed. The format of the volume label on the FAT volume is similar to the file name but there are some differences shown below:

    +

    When the string has a drive prefix, the volume label will be set to the volume specified by the drive prefix. Unix style volume ID cannot be used to specify the volume. If drive number is not specified, the volume label will be set to the default drive. If length of the given volume label is zero, the volume label on the volume will be removed. The format of the volume label is as shown below:

    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.

    diff --git a/documents/doc/sfileinfo.html b/documents/doc/sfileinfo.html index c9597a9..7717580 100644 --- a/documents/doc/sfileinfo.html +++ b/documents/doc/sfileinfo.html @@ -57,7 +57,16 @@
    fattrib
    -
    Indicates the file/directory attribute in combination of AM_DIR, AM_RDO, AM_HID, AM_SYS and AM_ARC.
    +
    Indicates the attribute flags in combination of:
    + + + + + + + +
    FlagMeaning
    AM_RDORead-only. Write mode open and deleting is rejected.
    AM_HIDHidden. Should not be shown in normal directory listing.
    AM_SYSSystem. Used by system and should not be accessed.
    AM_ARCArchive. Set on new creation or any modification to the file.
    AM_DIRDirectory. This is not a file but a sub-directory container.
    +
    fname[]
    The null-terminated object name is stored. 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 at LFN configuration.
    altname[]
    diff --git a/documents/doc/stat.html b/documents/doc/stat.html index b0012cf..cc5c03d 100644 --- a/documents/doc/stat.html +++ b/documents/doc/stat.html @@ -26,7 +26,7 @@ FRESULT f_stat (

    Parameters

    path
    -
    Pointer to the null-terminated string that specifies the object to get its information.
    +
    Pointer to the null-terminated string that specifies the object to get its information. The object must not be the root direcotry.
    fno
    Pointer to the blank FILINFO structure to store the information of the object. Set null pointer if it is not needed.
    diff --git a/documents/doc/write.html b/documents/doc/write.html index e5401a4..f6772d7 100644 --- a/documents/doc/write.html +++ b/documents/doc/write.html @@ -34,7 +34,7 @@ FRESULT f_write (
    btw
    Specifies number of bytes to write in range of UINT type.
    bw
    -
    Pointer to the UINT variable to return the number of bytes written. This value is always valid after the function call regardless of the return value.
    +
    Pointer to the UINT variable to return the number of bytes written. This value is always valid after the function call regardless of the function return code.
    diff --git a/documents/updates.txt b/documents/updates.txt index f15d4d5..3b7d126 100644 --- a/documents/updates.txt +++ b/documents/updates.txt @@ -1,3 +1,9 @@ +R0.13b (April 07, 2018) + Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3) + Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2) + Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c) + Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b) + R0.13a (October 14, 2017) Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2) Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF). diff --git a/source/00history.txt b/source/00history.txt index 6789ab0..9b67d02 100644 --- a/source/00history.txt +++ b/source/00history.txt @@ -312,3 +312,13 @@ R0.13a (October 14, 2017) Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12) + +R0.13b (April 07, 2018) + + Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3) + Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2) + Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c) + Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b) + + + diff --git a/source/00readme.txt b/source/00readme.txt index 6eff7fc..15426d2 100644 --- a/source/00readme.txt +++ b/source/00readme.txt @@ -1,4 +1,4 @@ -FatFs Module Source Files R0.13a +FatFs Module Source Files R0.13b FILES diff --git a/source/diskio.h b/source/diskio.h index 20ebde9..1fa4400 100644 --- a/source/diskio.h +++ b/source/diskio.h @@ -46,11 +46,11 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); /* Command code for disk_ioctrl fucntion */ /* Generic command (Used by FatFs) */ -#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ -#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ -#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ -#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ -#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ +#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ +#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ +#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ /* Generic command (Not used by FatFs) */ #define CTRL_POWER 5 /* Get/Set power status */ diff --git a/source/ff.c b/source/ff.c index d29601d..35c9755 100644 --- a/source/ff.c +++ b/source/ff.c @@ -1,8 +1,8 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem Module R0.13a / +/ FatFs - Generic FAT Filesystem Module R0.13b / /-----------------------------------------------------------------------------/ / -/ Copyright (C) 2017, ChaN, all right reserved. +/ Copyright (C) 2018, 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 @@ -29,7 +29,7 @@ ---------------------------------------------------------------------------*/ -#if FF_DEFINED != 89352 /* Revision ID */ +#if FF_DEFINED != 63463 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -426,10 +426,10 @@ typedef struct { #if FF_VOLUMES < 1 || FF_VOLUMES > 10 #error Wrong FF_VOLUMES setting #endif -static FATFS *FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ -static WORD Fsid; /* File system mount ID */ +static FATFS* FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ +static WORD Fsid; /* Filesystem mount ID */ -#if FF_FS_RPATH != 0 && FF_VOLUMES >= 2 +#if FF_FS_RPATH != 0 static BYTE CurrVol; /* Current drive */ #endif @@ -437,6 +437,11 @@ static BYTE CurrVol; /* Current drive */ static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ #endif +#if FF_STR_VOLUME_ID +#ifdef FF_VOLUME_STRS +static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ +#endif +#endif /*--------------------------------*/ @@ -456,10 +461,10 @@ static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ #if FF_MAX_LFN < 12 || FF_MAX_LFN > 255 #error Wrong setting of FF_MAX_LFN #endif -#if FF_LFN_BUF < 12 || FF_SFN_BUF < 12 || FF_LFN_BUF < FF_SFN_BUF +#if FF_LFN_BUF < FF_SFN_BUF || FF_SFN_BUF < 12 #error Wrong setting of FF_LFN_BUF or FF_SFN_BUF #endif -#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 2 +#if FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3 #error Wrong setting of FF_LFN_UNICODE #endif static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* FAT: Offset of LFN characters in the directory entry */ @@ -498,7 +503,7 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ #define FREE_NAMBUF() ff_memfree(lfn) #endif #define LEAVE_MKFS(res) { if (!work) ff_memfree(buf); return res; } -#define MAX_MALLOC 0x8000 +#define MAX_MALLOC 0x8000 /* Must be >=FF_MAX_SS */ #else #error Wrong setting of FF_USE_LFN @@ -562,8 +567,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_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ { WORD rv; @@ -572,8 +576,7 @@ 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_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ { DWORD rv; @@ -585,8 +588,7 @@ 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_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ { QWORD rv; @@ -603,15 +605,13 @@ 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_word (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_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; @@ -620,8 +620,7 @@ void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ } #if FF_FS_EXFAT -static -void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ +static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ { *ptr++ = (BYTE)val; val >>= 8; *ptr++ = (BYTE)val; val >>= 8; @@ -642,8 +641,7 @@ void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ /*-----------------------------------------------------------------------*/ /* Copy memory to memory */ -static -void mem_cpy (void* dst, const void* src, UINT cnt) +static void mem_cpy (void* dst, const void* src, UINT cnt) { BYTE *d = (BYTE*)dst; const BYTE *s = (const BYTE*)src; @@ -657,8 +655,7 @@ void mem_cpy (void* dst, const void* src, UINT cnt) /* Fill memory block */ -static -void mem_set (void* dst, int val, UINT cnt) +static void mem_set (void* dst, int val, UINT cnt) { BYTE *d = (BYTE*)dst; @@ -669,8 +666,7 @@ void mem_set (void* dst, int val, UINT cnt) /* Compare memory block */ -static -int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */ +static int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */ { const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; int r = 0; @@ -684,8 +680,7 @@ int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:differen /* Check if chr is contained in the string */ -static -int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ +static int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ { while (*str && *str != chr) str++; return *str; @@ -693,8 +688,7 @@ int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ /* Test if the character is DBC 1st byte */ -static -int dbc_1st (BYTE c) +static int dbc_1st (BYTE c) { #if FF_CODE_PAGE == 0 /* Variable code page */ if (DbcTbl && c >= DbcTbl[0]) { @@ -714,8 +708,7 @@ int dbc_1st (BYTE c) /* Test if the character is DBC 2nd byte */ -static -int dbc_2nd (BYTE c) +static int dbc_2nd (BYTE c) { #if FF_CODE_PAGE == 0 /* Variable code page */ if (DbcTbl && c >= DbcTbl[4]) { @@ -739,9 +732,8 @@ int dbc_2nd (BYTE c) #if FF_USE_LFN /* Get a character from TCHAR string in defined API encodeing */ -static -DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */ - const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ +static DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double encoding unit, 0xFFFFFFFF on decode error) */ + const TCHAR** str /* Pointer to pointer to TCHAR string in configured encoding */ ) { DWORD uc; @@ -750,7 +742,7 @@ DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double #if FF_LFN_UNICODE == 1 /* UTF-16 input */ WCHAR wc; - uc = *p++; + uc = *p++; /* Get a unit */ if (IsSurrogate(uc)) { /* Surrogate? */ wc = *p++; /* Get low surrogate */ if (!IsSurrogateH(uc) || !IsSurrogateL(wc)) return 0xFFFFFFFF; /* Wrong surrogate? */ @@ -761,7 +753,7 @@ DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double BYTE b; int nf; - uc = (BYTE)*p++; /* Get a byte */ + uc = (BYTE)*p++; /* Get a unit */ if (uc & 0x80) { /* Multiple byte code? */ if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */ uc &= 0x1F; nf = 1; @@ -782,9 +774,14 @@ DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double uc = uc << 6 | (b & 0x3F); } while (--nf != 0); if (uc < 0x80 || IsSurrogate(uc) || uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ - if (uc >= 0x10000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ } +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + uc = (TCHAR)*p++; /* Get a unit */ + if (uc >= 0x110000) return 0xFFFFFFFF; /* Wrong code? */ + if (uc >= 0x010000) uc = 0xD800DC00 | ((uc - 0x10000) << 6 & 0x3FF0000) | (uc & 0x3FF); /* Make a surrogate pair if needed */ + #else /* ANSI/OEM input */ BYTE b; WCHAR wc; @@ -808,8 +805,7 @@ DWORD tchar2uni ( /* Returns character in UTF-16 encoding (>=0x10000 on double /* Output a TCHAR string in defined API encoding */ -static -BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ +static BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */ DWORD chr, /* UTF-16 encoded character (Double encoding unit char if >=0x10000) */ TCHAR* buf, /* Output buffer */ UINT szb /* Size of the buffer */ @@ -863,6 +859,19 @@ BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or *buf++ = (TCHAR)(0x80 | (chr >> 0 & 0x3F)); return 4; +#elif FF_LFN_UNICODE == 3 /* UTF-32 output */ + DWORD hc; + + if (szb < 1) return 0; /* Buffer overflow? */ + if (chr >= 0x10000) { /* Out of BMP? */ + hc = ((chr & 0xFFFF0000) - 0xD8000000) >> 6; /* Get high 10 bits */ + chr = (chr & 0xFFFF) - 0xDC00; /* Get low 10 bits */ + if (hc >= 0x100000 || chr >= 0x400) return 0; /* Wrong surrogate? */ + chr = (hc | chr) + 0x10000; + } + *buf++ = (TCHAR)chr; + return 1; + #else /* ANSI/OEM output */ WCHAR wc; @@ -885,8 +894,7 @@ BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or /*-----------------------------------------------------------------------*/ /* Request/Release grant to access the volume */ /*-----------------------------------------------------------------------*/ -static -int lock_fs ( /* 1:Ok, 0:timeout */ +static int lock_fs ( /* 1:Ok, 0:timeout */ FATFS* fs /* Filesystem object */ ) { @@ -894,8 +902,7 @@ int lock_fs ( /* 1:Ok, 0:timeout */ } -static -void unlock_fs ( +static void unlock_fs ( FATFS* fs, /* Filesystem object */ FRESULT res /* Result code to be returned */ ) @@ -914,8 +921,7 @@ void unlock_fs ( /* File lock control functions */ /*-----------------------------------------------------------------------*/ -static -FRESULT chk_lock ( /* Check if the file can be accessed */ +static FRESULT chk_lock ( /* Check if the file can be accessed */ DIR* dp, /* Directory object pointing the file to be checked */ int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ ) @@ -942,8 +948,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ } -static -int enq_lock (void) /* Check if an entry is available for a new object */ +static int enq_lock (void) /* Check if an entry is available for a new object */ { UINT i; @@ -952,8 +957,7 @@ int enq_lock (void) /* Check if an entry is available for a new object */ } -static -UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ +static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ DIR* dp, /* Directory object pointing the file to register or increment */ int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ ) @@ -984,8 +988,7 @@ UINT inc_lock ( /* Increment object open counter and returns its index (0:Intern } -static -FRESULT dec_lock ( /* Decrement object open counter */ +static FRESULT dec_lock ( /* Decrement object open counter */ UINT i /* Semaphore index (1..) */ ) { @@ -1007,8 +1010,7 @@ FRESULT dec_lock ( /* Decrement object open counter */ } -static -void clear_lock ( /* Clear lock entries of the volume */ +static void clear_lock ( /* Clear lock entries of the volume */ FATFS *fs ) { @@ -1027,8 +1029,7 @@ void clear_lock ( /* Clear lock entries of the volume */ /* Move/Flush disk access window in the filesystem object */ /*-----------------------------------------------------------------------*/ #if !FF_FS_READONLY -static -FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ +static FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs /* Filesystem object */ ) { @@ -1050,8 +1051,7 @@ FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ #endif -static -FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ +static FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs, /* Filesystem object */ DWORD sector /* Sector number to make appearance in the fs->win[] */ ) @@ -1082,8 +1082,7 @@ FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ /* Synchronize filesystem and data on the storage */ /*-----------------------------------------------------------------------*/ -static -FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ +static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ FATFS* fs /* Filesystem object */ ) { @@ -1120,8 +1119,7 @@ FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ /* Get physical sector number from cluster number */ /*-----------------------------------------------------------------------*/ -static -DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ +static DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ FATFS* fs, /* Filesystem object */ DWORD clst /* Cluster# to be converted */ ) @@ -1138,8 +1136,7 @@ DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ /* FAT access - Read value of a FAT entry */ /*-----------------------------------------------------------------------*/ -static -DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ +static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ FFOBJID* obj, /* Corresponding object */ DWORD clst /* Cluster number to get the value */ ) @@ -1176,7 +1173,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Clust break; #if FF_FS_EXFAT case FS_EXFAT : - if (obj->objsize != 0) { + if ((obj->objsize != 0 && obj->sclust != 0) || obj->stat == 0) { /* Object except root dir must have valid data length */ DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ @@ -1216,8 +1213,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Clust /* FAT access - Change value of a FAT entry */ /*-----------------------------------------------------------------------*/ -static -FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ +static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ FATFS* fs, /* Corresponding filesystem object */ DWORD clst, /* FAT index number (cluster number) to be changed */ DWORD val /* New value to be set to the entry */ @@ -1282,8 +1278,7 @@ FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ /* Find a contiguous free cluster block */ /*--------------------------------------*/ -static -DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ +static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ FATFS* fs, /* Filesystem object */ DWORD clst, /* Cluster number to scan from */ DWORD ncl /* Number of contiguous clusters to find (1..) */ @@ -1323,8 +1318,7 @@ DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk err /* Set/Clear a block of allocation bitmap */ /*----------------------------------------*/ -static -FRESULT change_bitmap ( +static FRESULT change_bitmap ( FATFS* fs, /* Filesystem object */ DWORD clst, /* Cluster number to change from */ DWORD ncl, /* Number of clusters to be changed */ @@ -1360,8 +1354,7 @@ FRESULT change_bitmap ( /* Fill the first fragment of the FAT chain */ /*---------------------------------------------*/ -static -FRESULT fill_first_frag ( +static FRESULT fill_first_frag ( FFOBJID* obj /* Pointer to the corresponding object */ ) { @@ -1384,8 +1377,7 @@ FRESULT fill_first_frag ( /* Fill the last fragment of the FAT chain */ /*---------------------------------------------*/ -static -FRESULT fill_last_frag ( +static FRESULT fill_last_frag ( FFOBJID* obj, /* Pointer to the corresponding object */ DWORD lcl, /* Last cluster of the fragment */ DWORD term /* Value to set the last FAT entry */ @@ -1410,8 +1402,8 @@ FRESULT fill_last_frag ( /*-----------------------------------------------------------------------*/ /* FAT handling - Remove a cluster chain */ /*-----------------------------------------------------------------------*/ -static -FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ + +static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ FFOBJID* obj, /* Corresponding object */ DWORD clst, /* Cluster to remove a chain from */ DWORD pclst /* Previous cluster of clst (0:entire chain) */ @@ -1505,8 +1497,8 @@ FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ /*-----------------------------------------------------------------------*/ /* FAT handling - Stretch a chain or Create a new chain */ /*-----------------------------------------------------------------------*/ -static -DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + +static DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ FFOBJID* obj, /* Corresponding object */ DWORD clst /* Cluster# to stretch, 0:Create a new chain */ ) @@ -1609,8 +1601,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err /* FAT handling - Convert offset into cluster with link map table */ /*-----------------------------------------------------------------------*/ -static -DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ +static DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ FIL* fp, /* Pointer to the file object */ FSIZE_t ofs /* File offset to be converted to cluster# */ ) @@ -1640,8 +1631,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ /*-----------------------------------------------------------------------*/ #if !FF_FS_READONLY -static -FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ +static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ FATFS *fs, /* Filesystem object */ DWORD clst /* Directory table to clear */ ) @@ -1657,7 +1647,7 @@ FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */ #if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ /* Allocate a temporary buffer */ - for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs); szb > SS(fs) && !(ibuf = ff_memalloc(szb)); szb /= 2) ; + for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ; if (szb > SS(fs)) { /* Buffer allocated? */ mem_set(ibuf, 0, szb); szb /= SS(fs); /* Bytes -> Sectors */ @@ -1666,7 +1656,7 @@ FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ } else #endif { - ibuf = fs->win; szb = 1; /* Use window buffer (single-sector writes may take a time) */ + ibuf = fs->win; szb = 1; /* Use window buffer (many single-sector writes may take a time) */ for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ } return (n == fs->csize) ? FR_OK : FR_DISK_ERR; @@ -1680,8 +1670,7 @@ FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ /* Directory handling - Set directory index */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ +static FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ DIR* dp, /* Pointer to directory object */ DWORD ofs /* Offset of directory table */ ) @@ -1729,10 +1718,9 @@ FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ /* Directory handling - Move directory table index next */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ - DIR* dp, /* Pointer to the directory object */ - int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + DIR* dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ ) { DWORD ofs, clst; @@ -1790,10 +1778,9 @@ FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Cou /* Directory handling - Reserve a block of directory entries */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ - DIR* dp, /* Pointer to the directory object */ - UINT nent /* Number of contiguous entries to allocate */ +static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp, /* Pointer to the directory object */ + UINT nent /* Number of contiguous entries to allocate */ ) { FRESULT res; @@ -1833,10 +1820,9 @@ FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ /* FAT: Directory handling - Load/Store start cluster number */ /*-----------------------------------------------------------------------*/ -static -DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ - FATFS* fs, /* Pointer to the fs object */ - const BYTE* dir /* Pointer to the key entry */ +static DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ + FATFS* fs, /* Pointer to the fs object */ + const BYTE* dir /* Pointer to the key entry */ ) { DWORD cl; @@ -1851,8 +1837,7 @@ DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ #if !FF_FS_READONLY -static -void st_clust ( +static void st_clust ( FATFS* fs, /* Pointer to the fs object */ BYTE* dir, /* Pointer to the key entry */ DWORD cl /* Value to be set */ @@ -1871,8 +1856,8 @@ void st_clust ( /*--------------------------------------------------------*/ /* FAT-LFN: Compare a part of file name with an LFN entry */ /*--------------------------------------------------------*/ -static -int cmp_lfn ( /* 1:matched, 0:not matched */ + +static int cmp_lfn ( /* 1:matched, 0:not matched */ const WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */ BYTE* dir /* Pointer to the directory entry containing the part of LFN */ ) @@ -1907,8 +1892,8 @@ int cmp_lfn ( /* 1:matched, 0:not matched */ /*-----------------------------------------------------*/ /* FAT-LFN: Pick a part of file name from an LFN entry */ /*-----------------------------------------------------*/ -static -int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ + +static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ WCHAR* lfnbuf, /* Pointer to the LFN working buffer */ BYTE* dir /* Pointer to the LFN entry */ ) @@ -1945,8 +1930,8 @@ int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ /*-----------------------------------------*/ /* FAT-LFN: Create an entry of LFN entries */ /*-----------------------------------------*/ -static -void put_lfn ( + +static void put_lfn ( const WCHAR* lfn, /* Pointer to the LFN */ BYTE* dir, /* Pointer to the LFN entry to be created */ BYTE ord, /* LFN order (1-20) */ @@ -1983,8 +1968,7 @@ void put_lfn ( /* FAT-LFN: Create a Numbered SFN */ /*-----------------------------------------------------------------------*/ -static -void gen_numname ( +static void gen_numname ( BYTE* dst, /* Pointer to the buffer to store numbered SFN */ const BYTE* src, /* Pointer to SFN */ const WCHAR* lfn, /* Pointer to LFN */ @@ -2001,7 +1985,7 @@ void gen_numname ( if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */ sr = seq; - while (*lfn) { /* Create a CRC */ + while (*lfn) { /* Create a CRC as hash value */ wc = *lfn++; for (i = 0; i < 16; i++) { sr = (sr << 1) + (wc & 1); @@ -2042,8 +2026,7 @@ void gen_numname ( /* FAT-LFN: Calculate checksum of an SFN entry */ /*-----------------------------------------------------------------------*/ -static -BYTE sum_sfn ( +static BYTE sum_sfn ( const BYTE* dir /* Pointer to the SFN entry */ ) { @@ -2065,8 +2048,7 @@ BYTE sum_sfn ( /* exFAT: Checksum */ /*-----------------------------------------------------------------------*/ -static -WORD xdir_sum ( /* Get checksum of the directoly entry block */ +static WORD xdir_sum ( /* Get checksum of the directoly entry block */ const BYTE* dir /* Directory entry block to be calculated */ ) { @@ -2074,9 +2056,9 @@ WORD xdir_sum ( /* Get checksum of the directoly entry block */ WORD sum; - szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; + szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; /* Number of bytes of the entry block */ for (i = sum = 0; i < szblk; i++) { - if (i == XDIR_SetSum) { /* Skip sum field */ + if (i == XDIR_SetSum) { /* Skip 2-byte sum field */ i++; } else { sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; @@ -2087,8 +2069,7 @@ WORD xdir_sum ( /* Get checksum of the directoly entry block */ -static -WORD xname_sum ( /* Get check sum (to be used as hash) of the name */ +static WORD xname_sum ( /* Get check sum (to be used as hash) of the file name */ const WCHAR* name /* File name to be calculated */ ) { @@ -2097,7 +2078,7 @@ WORD xname_sum ( /* Get check sum (to be used as hash) of the name */ while ((chr = *name++) != 0) { - chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be upper-case converted */ + chr = (WCHAR)ff_wtoupper(chr); /* File name needs to be up-case converted */ sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); } @@ -2106,10 +2087,9 @@ WORD xname_sum ( /* Get check sum (to be used as hash) of the name */ #if !FF_FS_READONLY && FF_USE_MKFS -static -DWORD xsum32 ( - BYTE dat, /* Byte to be calculated */ - DWORD sum /* Previous sum */ +static DWORD xsum32 ( /* Returns 32-bit checksum */ + BYTE dat, /* Byte to be calculated (byte-by-byte processing) */ + DWORD sum /* Previous sum value */ ) { sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; @@ -2123,8 +2103,7 @@ DWORD xsum32 ( /* exFAT: Get object information from a directory block */ /*------------------------------------------------------*/ -static -void get_xfileinfo ( +static void get_xfileinfo ( BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */ FILINFO* fno /* Buffer to store the extracted file information */ ) @@ -2134,7 +2113,7 @@ void get_xfileinfo ( /* Get file name from the entry block */ si = SZDIRE * 2; /* 1st C1 entry */ - nc = hs = di = 0; + nc = 0; hs = 0; di = 0; while (nc < dirb[XDIR_NumName]) { if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */ if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ @@ -2142,7 +2121,7 @@ void get_xfileinfo ( if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */ hs = wc; continue; /* Get low surrogate */ } - wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in UTF-16 or UTF-8 encoding */ + wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */ if (wc == 0) { di = 0; break; } /* Buffer overflow or wrong encoding? */ di += wc; hs = 0; @@ -2150,7 +2129,7 @@ void get_xfileinfo ( if (hs != 0) di = 0; /* Broken surrogate pair? */ if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ fno->fname[di] = 0; /* Terminate the name */ - fno->altname[0] = 0; /* exFAT does not have SFN */ + fno->altname[0] = 0; /* exFAT does not support SFN */ fno->fattrib = dirb[XDIR_Attr]; /* Attribute */ fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */ @@ -2165,9 +2144,8 @@ void get_xfileinfo ( /* exFAT: Get a directry entry block */ /*-----------------------------------*/ -static -FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ - DIR* dp /* Reading direcotry object pointing top of the entry block to load */ +static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ + DIR* dp /* Reading direcotry object pointing top of the entry block to load */ ) { FRESULT res; @@ -2217,8 +2195,7 @@ FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ /* exFAT: Initialize object allocation info with loaded entry block */ /*------------------------------------------------------------------*/ -static -void init_alloc_info ( +static void init_alloc_info ( FATFS* fs, /* Filesystem object */ FFOBJID* obj /* Object allocation information to be initialized */ ) @@ -2235,8 +2212,8 @@ void init_alloc_info ( /*------------------------------------------------*/ /* exFAT: Load the object's directory entry block */ /*------------------------------------------------*/ -static -FRESULT load_obj_xdir ( + +static FRESULT load_obj_xdir ( DIR* dp, /* Blank directory object to be used to access containing direcotry */ const FFOBJID* obj /* Object with its containing directory information */ ) @@ -2264,8 +2241,8 @@ FRESULT load_obj_xdir ( /*----------------------------------------*/ /* exFAT: Store the directory entry block */ /*----------------------------------------*/ -static -FRESULT store_xdir ( + +static FRESULT store_xdir ( DIR* dp /* Pointer to the direcotry object */ ) { @@ -2297,8 +2274,7 @@ FRESULT store_xdir ( /* exFAT: Create a new directory enrty block */ /*-------------------------------------------*/ -static -void create_xdir ( +static void create_xdir ( BYTE* dirb, /* Pointer to the direcotry entry block buffer */ const WCHAR* lfn /* Pointer to the object name */ ) @@ -2344,8 +2320,7 @@ void create_xdir ( #define dir_read_file(dp) dir_read(dp, 0) #define dir_read_label(dp) dir_read(dp, 1) -static -FRESULT dir_read ( +static FRESULT dir_read ( DIR* dp, /* Pointer to the directory object */ int vol /* Filtered by 0:file/directory or 1:volume label */ ) @@ -2423,9 +2398,8 @@ FRESULT dir_read ( /* Directory handling - Find an object in the directory */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ - DIR* dp /* Pointer to the directory object with the file name */ +static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp /* Pointer to the directory object with the file name */ ) { FRESULT res; @@ -2505,9 +2479,8 @@ FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ /* Register an object to the directory */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ - DIR* dp /* Target directory with object name to be created */ +static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ + DIR* dp /* Target directory with object name to be created */ ) { FRESULT res; @@ -2612,9 +2585,8 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S /* Remove an object from the directory */ /*-----------------------------------------------------------------------*/ -static -FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ - DIR* dp /* Directory object pointing the entry to be removed */ +static FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ + DIR* dp /* Directory object pointing the entry to be removed */ ) { FRESULT res; @@ -2659,10 +2631,9 @@ FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ /* Get file information from directory entry */ /*-----------------------------------------------------------------------*/ -static -void get_fileinfo ( - DIR* dp, /* Pointer to the directory object */ - FILINFO* fno /* Pointer to the file information to be filled */ +static void get_fileinfo ( + DIR* dp, /* Pointer to the directory object */ + FILINFO* fno /* Pointer to the file information to be filled */ ) { UINT si, di; @@ -2714,7 +2685,7 @@ void get_fileinfo ( } wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */ if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */ - wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in UTF-16 or UTF-8 */ + wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in Unicode */ if (wc == 0) { di = 0; break; } /* Buffer overflow? */ di += wc; #else /* ANSI/OEM output */ @@ -2764,9 +2735,8 @@ void get_fileinfo ( /* Pattern matching */ /*-----------------------------------------------------------------------*/ -static -DWORD get_achar ( /* Get a character and advances ptr */ - const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ +static DWORD get_achar ( /* Get a character and advances ptr */ + const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */ ) { DWORD chr; @@ -2796,8 +2766,7 @@ DWORD get_achar ( /* Get a character and advances ptr */ } -static -int pattern_matching ( /* 0:not matched, 1:matched */ +static int pattern_matching ( /* 0:not matched, 1:matched */ const TCHAR* pat, /* Matching pattern */ const TCHAR* nam, /* String to be tested */ int skip, /* Number of pre-skip chars (number of ?s) */ @@ -2844,10 +2813,9 @@ int pattern_matching ( /* 0:not matched, 1:matched */ /* Pick a top segment and create the object name in directory form */ /*-----------------------------------------------------------------------*/ -static -FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ - DIR* dp, /* Pointer to the directory object */ - const TCHAR** path /* Pointer to pointer to the segment in the path string */ +static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ + DIR* dp, /* Pointer to the directory object */ + const TCHAR** path /* Pointer to pointer to the segment in the path string */ ) { #if FF_USE_LFN /* LFN configuration */ @@ -3042,10 +3010,9 @@ FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ /* Follow a file path */ /*-----------------------------------------------------------------------*/ -static -FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ - DIR* dp, /* Directory object to return last directory and found object */ - const TCHAR* path /* Full-path string to find a file or directory */ +static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR* dp, /* Directory object to return last directory and found object */ + const TCHAR* path /* Full-path string to find a file or directory */ ) { FRESULT res; @@ -3130,58 +3097,71 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ /* Get logical drive number from path name */ /*-----------------------------------------------------------------------*/ -static -int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ - const TCHAR** path /* Pointer to pointer to the path name */ +static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive number or null pointer) */ + const TCHAR** path /* Pointer to pointer to the path name */ ) { const TCHAR *tp, *tt; - UINT i; - int vol = -1; -#if FF_STR_VOLUME_ID /* Find string drive id */ - static const char* const volid[] = {FF_VOLUME_STRS}; + TCHAR tc; + int i, vol = -1; +#if FF_STR_VOLUME_ID /* Find string volume ID */ const char *sp; char c; - TCHAR tc; #endif + tt = tp = *path; + if (!tp) return vol; /* Invalid path name? */ + do tc = *tt++; while ((UINT)tc >= (FF_USE_LFN ? ' ' : '!') && tc != ':'); /* Find a colon in the path */ - if (*path != 0) { /* If the pointer is not a null */ - for (tt = *path; (UINT)*tt >= (FF_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find a colon in the path */ - if (*tt == ':') { /* If a colon is exist in the path name */ - tp = *path; - i = *tp++; - if (IsDigit(i) && tp == tt) { /* Is there a numeric drive id + colon? */ - if ((i -= '0') < FF_VOLUMES) { /* If drive id is found, get the value and strip it */ - vol = (int)i; - *path = ++tt; - } - } -#if FF_STR_VOLUME_ID - else { /* No numeric drive number, find string drive id */ - i = 0; tt++; - do { - sp = volid[i]; tp = *path; - do { /* Compare a string drive id with path name */ - c = *sp++; tc = *tp++; - if (IsLower(tc)) tc -= 0x20; - } while (c && (TCHAR)c == tc); - } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ - if (i < FF_VOLUMES) { /* If a drive id is found, get the value and strip it */ - vol = (int)i; - *path = tt; - } - } -#endif - } else { /* No volume id and use default drive */ -#if FF_FS_RPATH != 0 && FF_VOLUMES >= 2 - vol = CurrVol; /* Current drive */ -#else - vol = 0; /* Drive 0 */ + if (tc == ':') { /* DOS/Windows style volume ID? */ + i = FF_VOLUMES; + if (IsDigit(*tp) && tp + 2 == tt) { /* Is there a numeric volume ID + colon? */ + i = (int)*tp - '0'; /* Get the LD number */ + } +#if FF_STR_VOLUME_ID == 1 /* Arbitrary string is enabled */ + else { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *tp++; + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ + } #endif + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tt; /* Snip the drive prefix off */ + } + return vol; + } +#if FF_STR_VOLUME_ID == 2 /* Unix style volume ID is enabled */ + if (*tp == '/') { + i = 0; + do { + sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */ + do { /* Compare the volume ID with path name */ + c = *sp++; tc = *(++tp); + if (IsLower(c)) c -= 0x20; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || (tc != '/' && (UINT)tc >= (FF_USE_LFN ? ' ' : '!'))) && ++i < FF_VOLUMES); /* Repeat for each ID until pattern match */ + if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */ + vol = i; /* Drive number */ + *path = tp; /* Snip the drive prefix off */ + return vol; } } - return vol; +#endif + /* No drive prefix is found */ +#if FF_FS_RPATH != 0 + vol = CurrVol; /* Default drive is current drive */ +#else + vol = 0; /* Default drive is 0 */ +#endif + return vol; /* Return the default drive */ } @@ -3191,16 +3171,15 @@ int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ /* Load a sector and check if it is an FAT VBR */ /*-----------------------------------------------------------------------*/ -static -BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ - FATFS* fs, /* Filesystem object */ - DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ +static BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ ) { fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */ - if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always placed here even if the sector size is >512) */ + if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always here regardless of the sector size) */ #if FF_FS_EXFAT if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* Check if exFAT VBR */ @@ -3219,11 +3198,10 @@ BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk er /* Determine logical drive number and mount the volume if needed */ /*-----------------------------------------------------------------------*/ -static -FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ - const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ - FATFS** rfs, /* Pointer to pointer to the found filesystem object */ - BYTE mode /* !=0: Check write protection for write access */ +static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */ + const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ + FATFS** rfs, /* Pointer to pointer to the found filesystem object */ + BYTE mode /* !=0: Check write protection for write access */ ) { BYTE fmt, *pt; @@ -3445,10 +3423,9 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ /* Check if the file/directory object is valid or not */ /*-----------------------------------------------------------------------*/ -static -FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ - FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ - FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ +static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ + FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ + FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ ) { FRESULT res = FR_INVALID_OBJECT; @@ -3556,7 +3533,7 @@ FRESULT f_open ( if (!fp) return FR_INVALID_OBJECT; - /* Get logical drive */ + /* Get logical drive number */ mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND; res = find_volume(&path, &fs, mode); if (res == FR_OK) { @@ -3750,7 +3727,7 @@ FRESULT f_read ( remain = fp->obj.objsize - fp->fptr; if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ - for ( ; btr; /* Repeat until all data read */ + for ( ; btr; /* Repeat until btr bytes read */ btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ @@ -4066,9 +4043,8 @@ FRESULT f_close ( /* Change Current Directory or Current Drive, Get Current Directory */ /*-----------------------------------------------------------------------*/ -#if FF_VOLUMES >= 2 FRESULT f_chdrive ( - const TCHAR* path /* Drive number */ + const TCHAR* path /* Drive number to set */ ) { int vol; @@ -4077,23 +4053,26 @@ FRESULT f_chdrive ( /* Get logical drive number */ vol = get_ldnumber(&path); if (vol < 0) return FR_INVALID_DRIVE; - CurrVol = (BYTE)vol; /* Set it as current volume */ return FR_OK; } -#endif + FRESULT f_chdir ( const TCHAR* path /* Pointer to the directory path */ ) { +#if FF_STR_VOLUME_ID == 2 + UINT i; +#endif FRESULT res; DIR dj; FATFS *fs; DEF_NAMBUF + /* Get logical drive */ res = find_volume(&path, &fs, 0); if (res == FR_OK) { @@ -4101,8 +4080,8 @@ FRESULT f_chdir ( INIT_NAMBUF(fs); res = follow_path(&dj, path); /* Follow the path */ if (res == FR_OK) { /* Follow completed */ - if (dj.fn[NSFLAG] & NS_NONAME) { - fs->cdir = dj.obj.sclust; /* It is the start directory itself */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it the start directory itself? */ + fs->cdir = dj.obj.sclust; #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { fs->cdc_scl = dj.obj.c_scl; @@ -4130,6 +4109,12 @@ FRESULT f_chdir ( } FREE_NAMBUF(); if (res == FR_NO_FILE) res = FR_NO_PATH; +#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed at Unix style volume ID */ + if (res == FR_OK) { + for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */ + CurrVol = (BYTE)i; + } +#endif } LEAVE_FF(fs, res); @@ -4139,7 +4124,7 @@ FRESULT f_chdir ( #if FF_FS_RPATH >= 2 FRESULT f_getcwd ( TCHAR* buff, /* Pointer to the directory path */ - UINT len /* Size of path */ + UINT len /* Size of buff in unit of TCHAR */ ) { FRESULT res; @@ -4147,17 +4132,24 @@ FRESULT f_getcwd ( FATFS *fs; UINT i, n; DWORD ccl; - TCHAR *tp; + TCHAR *tp = buff; +#if FF_VOLUMES >= 2 + UINT vl; +#endif +#if FF_STR_VOLUME_ID + const char *vp; +#endif FILINFO fno; DEF_NAMBUF - *buff = 0; /* Get logical drive */ res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ if (res == FR_OK) { dj.obj.fs = fs; INIT_NAMBUF(fs); + + /* Follow parent directories and create the path */ i = len; /* Bottom of buffer (directory stack base) */ if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) */ dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ @@ -4178,32 +4170,44 @@ FRESULT f_getcwd ( if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ if (res != FR_OK) break; get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ - for (n = 0; fno.fname[n]; n++) ; - if (i < n + 3) { + for (n = 0; fno.fname[n]; n++) ; /* Name length */ + if (i < n + 1) { /* Insufficient space to store the path name? */ res = FR_NOT_ENOUGH_CORE; break; } - while (n) buff[--i] = fno.fname[--n]; + while (n) buff[--i] = fno.fname[--n]; /* Stack the name */ buff[--i] = '/'; } } - tp = buff; if (res == FR_OK) { -#if FF_VOLUMES >= 2 - *tp++ = '0' + CurrVol; /* Put drive number */ - *tp++ = ':'; + if (i == len) buff[--i] = '/'; /* Is it the root-directory? */ +#if FF_VOLUMES >= 2 /* Put drive prefix */ + vl = 0; +#if FF_STR_VOLUME_ID >= 1 /* String volume ID */ + for (n = 0, vp = (const char*)VolumeStr[CurrVol]; vp[n]; n++) ; + if (i >= n + 2) { + if (FF_STR_VOLUME_ID == 2) *tp++ = (TCHAR)'/'; + for (vl = 0; vl < n; *tp++ = (TCHAR)vp[vl], vl++) ; + if (FF_STR_VOLUME_ID == 1) *tp++ = (TCHAR)':'; + vl++; + } +#else /* Numeric volume ID */ + if (i >= 3) { + *tp++ = (TCHAR)'0' + CurrVol; + *tp++ = (TCHAR)':'; + vl = 2; + } #endif - if (i == len) { /* Root-directory */ - *tp++ = '/'; - } else { /* Sub-directroy */ - do /* Add stacked path str */ - *tp++ = buff[i++]; - while (i < len); + if (vl == 0) res = FR_NOT_ENOUGH_CORE; +#endif + /* Add current directory path */ + if (res == FR_OK) { + do *tp++ = buff[i++]; while (i < len); /* Copy stacked path string */ } } - *tp = 0; FREE_NAMBUF(); } + *tp = 0; LEAVE_FF(fs, res); } @@ -5168,8 +5172,8 @@ FRESULT f_getlabel ( wc = dj.dir[si++]; #if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode output */ if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++]; /* Is it a DBC? */ - wc = ff_oem2uni(wc, CODEPAGE); - if (wc != 0) wc = put_utf(wc, &label[di], 4); + wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */ + if (wc != 0) wc = put_utf(wc, &label[di], 4); /* Put it in Unicode */ if (wc == 0) { di = 0; break; } di += wc; #else /* ANSI/OEM output */ @@ -5227,7 +5231,7 @@ FRESULT f_setlabel ( BYTE dirvn[22]; UINT di; WCHAR wc; - static const char badchr[] = "+.,;=[]\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */ + static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */ #if FF_USE_LFN DWORD dc; #endif @@ -5240,7 +5244,7 @@ FRESULT f_setlabel ( if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ mem_set(dirvn, 0, 22); di = 0; - while (*label) { /* Create volume label in directory form */ + while ((UINT)*label >= ' ') { /* Create volume label */ dc = tchar2uni(&label); /* Get a Unicode character */ if (dc >= 0x10000) { if (dc == 0xFFFFFFFF || di >= 10) { /* Wrong surrogate or buffer overflow */ @@ -5259,7 +5263,7 @@ FRESULT f_setlabel ( { /* On the FAT/FAT32 volume */ mem_set(dirvn, ' ', 11); di = 0; - while (*label) { /* Create volume label in directory form */ + while ((UINT)*label >= ' ') { /* Create volume label */ #if FF_USE_LFN dc = tchar2uni(&label); wc = (dc < 0x10000) ? ff_uni2oem(ff_wtoupper(dc), CODEPAGE) : 0; @@ -5547,7 +5551,7 @@ FRESULT f_mkfs ( /* Get working buffer */ #if FF_USE_LFN == 3 if (!work) { /* Use heap memory for working buffer */ - for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && !(buf = ff_memalloc(szb_buf)); szb_buf /= 2) ; + for (szb_buf = MAX_MALLOC, buf = 0; szb_buf >= ss && (buf = ff_memalloc(szb_buf)) == 0; szb_buf /= 2) ; sz_buf = szb_buf / ss; /* Size of working buffer (sector) */ } else #endif @@ -5625,7 +5629,7 @@ FRESULT f_mkfs ( /* Create a compressed up-case table */ sect = b_data + au * tbl[0]; /* Table start sector */ sum = 0; /* Table checksum to be stored in the 82 entry */ - st = si = i = j = szb_case = 0; + st = 0; si = 0; i = 0; j = 0; szb_case = 0; do { switch (st) { case 0: @@ -5645,7 +5649,7 @@ FRESULT f_mkfs ( break; default: - ch = (WCHAR)j; si += j; /* Number of chars to skip */ + ch = (WCHAR)j; si += (WCHAR)j; /* Number of chars to skip */ st = 0; } sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ @@ -5697,12 +5701,12 @@ FRESULT f_mkfs ( mem_set(buf, 0, szb_buf); buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */ buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */ - st_dword(buf + SZDIRE * 1 + 20, 2); - st_dword(buf + SZDIRE * 1 + 24, szb_bit); + st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */ + st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */ buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */ - st_dword(buf + SZDIRE * 2 + 4, sum); - st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); - st_dword(buf + SZDIRE * 2 + 24, szb_case); + st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */ + st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */ + st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */ sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */ do { /* Fill root directory sectors */ n = (nsect > sz_buf) ? sz_buf : nsect; @@ -5970,7 +5974,7 @@ FRESULT f_fdisk ( ) { UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; - BYTE s_hd, e_hd, *p, *buf; = (BYTE*)work; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; DSTATUS stat; DWORD sz_disk, sz_part, s_part; FRESULT res; @@ -5990,7 +5994,7 @@ FRESULT f_fdisk ( /* Determine the CHS without any consideration of the drive geometry */ for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; if (n == 256) n--; - e_hd = n - 1; + e_hd = (BYTE)(n - 1); sz_cyl = 63 * n; tot_cyl = sz_disk / sz_cyl; @@ -6054,68 +6058,22 @@ TCHAR* f_gets ( { int nc = 0; TCHAR *p = buff; - BYTE s[2]; + BYTE s[4]; UINT rc; - WCHAR wc; -#if FF_USE_LFN && ((FF_LFN_UNICODE == 1 && FF_STRF_ENCODE == 3) || (FF_LFN_UNICODE == 2 && FF_STRF_ENCODE != 3)) DWORD dc; +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE <= 2 + WCHAR wc; #endif -#if FF_USE_LFN && FF_LFN_UNICODE == 1 && FF_STRF_ENCODE == 3 +#if FF_USE_LFN && FF_LFN_UNICODE && FF_STRF_ENCODE == 3 UINT ct; #endif -#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* UTF-16 output */ -#if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */ - while (nc < len - 1) { - f_read(fp, s, 1, &rc); - if (rc != 1) break; - wc = s[0]; - if (dbc_1st((BYTE)wc)) { - f_read(fp, s, 1, &rc); - if (rc != 1 || !dbc_2nd(s[0])) continue; - wc = wc << 8 | s[0]; - } - wc = ff_oem2uni(wc, CODEPAGE); - if (wc == 0) continue; -#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ - while (nc < len - 1) { - f_read(fp, s, 2, &rc); - if (rc != 2) break; - wc = (FF_STRF_ENCODE == 1) ? s[1] << 8 | s[0] : s[0] << 8 | s[1]; -#elif FF_STRF_ENCODE == 3 /* Read a character in UTF-8 */ - while (nc < len - 2) { - f_read(fp, s, 1, &rc); - if (rc != 1) break; - dc = s[0]; - if (dc >= 0x80) { - ct = 0; - if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } - if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } - if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } - if (ct == 0) continue; - do { - f_read(fp, s, 1, &rc); - if (rc != 1 || (s[0] & 0xC0) != 0x80) break; - dc = dc << 6 | (s[0] & 0x3F); - } while (--ct); - if (ct || dc < 0x80 || dc >= 0x110000) continue; - } - if (dc >= 0x10000) { - wc = (WCHAR)(0xD800 | ((dc >> 10) - 0x40)); - *p++ = wc; nc++; - wc = (WCHAR)(0xDC00 | (dc & 0x3FF)); - } else { - wc = (WCHAR)dc; - } -#endif - /* Output it in UTF-16 encoding */ - if (FF_USE_STRFUNC == 2 && wc == '\r') continue; - *p++ = wc; nc++; - if (wc == '\n') break; - } - -#elif FF_USE_LFN && FF_LFN_UNICODE == 2 && FF_STRF_ENCODE != 3 /* UTF-8 output */ - while (nc < len - 4) { +#if FF_USE_LFN && FF_LFN_UNICODE /* With code conversion (Unicode API) */ + /* Make a room for the character and terminator */ + if (FF_LFN_UNICODE == 1) len -= (FF_STRF_ENCODE == 0) ? 1 : 2; + if (FF_LFN_UNICODE == 2) len -= (FF_STRF_ENCODE == 0) ? 3 : 4; + if (FF_LFN_UNICODE == 3) len -= 1; + while (nc < len) { #if FF_STRF_ENCODE == 0 /* Read a character in ANSI/OEM */ f_read(fp, s, 1, &rc); if (rc != 1) break; @@ -6127,26 +6085,53 @@ TCHAR* f_gets ( } dc = ff_oem2uni(wc, CODEPAGE); if (dc == 0) continue; -#else /* Read a character in UTF-16LE/BE */ +#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */ f_read(fp, s, 2, &rc); if (rc != 2) break; - dc = (FF_STRF_ENCODE == 1) ? s[1] << 8 | s[0] : s[0] << 8 | s[1]; - if (IsSurrogate(dc)) { + dc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (IsSurrogateL(dc)) continue; + if (IsSurrogateH(dc)) { f_read(fp, s, 2, &rc); if (rc != 2) break; - wc = (FF_STRF_ENCODE == 1) ? s[1] << 8 | s[0] : s[0] << 8 | s[1]; - if (!IsSurrogateH(dc) || !IsSurrogateL(wc)) continue; + wc = (FF_STRF_ENCODE == 1) ? ld_word(s) : s[0] << 8 | s[1]; + if (!IsSurrogateL(wc)) continue; dc = ((dc & 0x3FF) + 0x40) << 10 | (wc & 0x3FF); } +#else /* Read a character in UTF-8 */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + dc = s[0]; + if (dc >= 0x80) { /* Multi-byte character? */ + ct = 0; + if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } /* 2-byte? */ + if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte? */ + if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte? */ + if (ct == 0) continue; + f_read(fp, s, ct, &rc); /* Get trailing bytes */ + if (rc != ct) break; + rc = 0; + do { /* Merge trailing bytes */ + if ((s[rc] & 0xC0) != 0x80) break; + dc = dc << 6 | (s[rc] & 0x3F); + } while (++rc < ct); + if (rc != ct || dc < 0x80 || IsSurrogate(dc) || dc >= 0x110000) continue; /* Wrong encoding? */ + } #endif - /* Output it in UTF-8 encoding */ - if (FF_USE_STRFUNC == 2 && dc == '\r') continue; + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; /* Strip \r off if needed */ +#if FF_LFN_UNICODE == 1 || FF_LFN_UNICODE == 3 /* Output it in UTF-16/32 encoding */ + if (FF_LFN_UNICODE == 1 && dc >= 0x10000) { /* Out of BMP at UTF-16? */ + *p++ = (TCHAR)(0xD800 | ((dc >> 10) - 0x40)); nc++; /* Make and output high surrogate */ + dc = 0xDC00 | (dc & 0x3FF); /* Make low surrogate */ + } + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; /* End of line? */ +#elif FF_LFN_UNICODE == 2 /* Output it in UTF-8 encoding */ if (dc < 0x80) { /* 1-byte */ *p++ = (TCHAR)dc; nc++; - if (dc == '\n') break; + if (dc == '\n') break; /* End of line? */ } else { - if (dc < 0x800) { /* 2-byte */ + if (dc < 0x800) { /* 2-byte */ *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F)); *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); nc += 2; @@ -6165,21 +6150,23 @@ TCHAR* f_gets ( } } } +#endif } -#else /* Byte-by-byte without any conversion (ANSI/OEM API or UTF-8 to UTF-8) */ - while (nc < len - 1) { +#else /* Byte-by-byte without any conversion (ANSI/OEM API) */ + len -= 1; /* Make a room for the terminator */ + while (nc < len) { f_read(fp, s, 1, &rc); if (rc != 1) break; - wc = s[0]; - if (FF_USE_STRFUNC == 2 && wc == '\r') continue; - *p++ = (TCHAR)wc; nc++; - if (wc == '\n') break; + dc = s[0]; + if (FF_USE_STRFUNC == 2 && dc == '\r') continue; + *p++ = (TCHAR)dc; nc++; + if (dc == '\n') break; } #endif - *p = 0; - return nc ? buff : 0; /* When no data read (EOF or error), return with error. */ + *p = 0; /* Terminate the string */ + return nc ? buff : 0; /* When no data read due to EOF or error, return with error. */ } @@ -6212,12 +6199,12 @@ void putc_bfd ( /* Buffered write with code conversion */ { UINT n; int i, nc; -#if FF_USE_LFN && (FF_LFN_UNICODE == 1 || (FF_LFN_UNICODE == 2 && (FF_STRF_ENCODE != 3))) +#if FF_USE_LFN && FF_LFN_UNICODE WCHAR hs, wc; -#endif -#if FF_USE_LFN && FF_LFN_UNICODE == 2 && FF_STRF_ENCODE != 3 +#if FF_LFN_UNICODE == 2 DWORD dc; TCHAR *tp; +#endif #endif if (FF_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */ @@ -6226,45 +6213,21 @@ void putc_bfd ( /* Buffered write with code conversion */ i = pb->idx; /* Write index of pb->buf[] */ if (i < 0) return; - nc = pb->nchr; /* Write unit count */ + nc = pb->nchr; /* Write unit counter */ -#if FF_USE_LFN && FF_LFN_UNICODE >= 1 -#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* UTF-16 input */ +#if FF_USE_LFN && FF_LFN_UNICODE +#if FF_LFN_UNICODE == 1 /* UTF-16 input */ if (IsSurrogateH(c)) { pb->hs = c; return; } - wc = c; hs = pb->hs; pb->hs = 0; + hs = pb->hs; pb->hs = 0; if (hs != 0) { - if (!IsSurrogateL(wc)) hs = 0; + if (!IsSurrogateL(c)) hs = 0; } else { - if (IsSurrogateL(wc)) return; + if (IsSurrogateL(c)) return; } -#if FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ - if (hs != 0) { /* 4-byte */ - nc += 4; - hs = (hs & 0x3FF) + 0x40; - pb->buf[i++] = (BYTE)(0xF0 | hs >> 8); - pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F)); - pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F)); - pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); - } else { - if (wc < 0x80) { /* 1-byte */ - nc++; - pb->buf[i++] = (BYTE)wc; - } else { - if (wc < 0x800) { /* 2-byte */ - nc += 2; - pb->buf[i++] = (BYTE)(0xC0 | wc >> 6); - } else { /* 3-byte */ - nc += 3; - pb->buf[i++] = (BYTE)(0xE0 | wc >> 12); - pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F)); - } - pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); - } - } -#endif -#else /* UTF-8 input */ + wc = c; +#elif FF_LFN_UNICODE == 2 /* UTF-8 input */ for (;;) { if (pb->ct == 0) { /* Out of multi-byte sequence? */ pb->bs[pb->wi = 0] = (BYTE)c; /* Save 1st byte */ @@ -6273,36 +6236,40 @@ void putc_bfd ( /* Buffered write with code conversion */ if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2; /* 3-byte? */ if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3; /* 4-byte? */ return; - } else { /* In the multi-byte sequence */ + } else { /* In the multi-byte sequence */ if (((BYTE)c & 0xC0) != 0x80) { /* Broken sequence? */ pb->ct = 0; continue; } pb->bs[++pb->wi] = (BYTE)c; /* Save the trailing byte */ - if (--pb->ct == 0) break; /* End of sequence? */ + if (--pb->ct == 0) break; /* End of multi-byte sequence? */ return; } } -#if FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ - pb->buf[i++] = pb->bs[0]; nc++; - if (pb->bs[0] >= 0xC0) { - pb->buf[i++] = pb->bs[1]; nc++; - } - if (pb->bs[0] >= 0xE0) { - pb->buf[i++] = pb->bs[2]; nc++; - } - if (pb->bs[0] >= 0xF0) { - pb->buf[i++] = pb->bs[3]; nc++; - } -#else /* Write it in UTF-16 or ANSI/OEM */ tp = (TCHAR*)pb->bs; dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ if (dc == 0xFFFFFFFF) return; wc = (WCHAR)dc; hs = (WCHAR)(dc >> 16); +#elif FF_LFN_UNICODE == 3 /* UTF-32 input */ + if (IsSurrogate(c) || c >= 0x110000) return; + if (c >= 0x10000) { + hs = (WCHAR)(0xD800 | ((c >> 10) - 0x40)); /* Make high surrogate */ + wc = 0xDC00 | (c & 0x3FF); /* Make low surrogate */ + } else { + hs = 0; + wc = (WCHAR)c; + } #endif -#endif -#if FF_USE_LFN && FF_LFN_UNICODE >= 1 && FF_STRF_ENCODE != 3 -#if FF_STRF_ENCODE == 2 /* Write a character in UTF-16BE */ + +#if FF_STRF_ENCODE == 1 /* Write a character in UTF-16LE */ + if (hs != 0) { + st_word(&pb->buf[i], hs); + i += 2; + nc++; + } + st_word(&pb->buf[i], wc); + i += 2; +#elif FF_STRF_ENCODE == 2 /* Write a character in UTF-16BE */ if (hs != 0) { pb->buf[i++] = (BYTE)(hs >> 8); pb->buf[i++] = (BYTE)hs; @@ -6310,30 +6277,41 @@ void putc_bfd ( /* Buffered write with code conversion */ } pb->buf[i++] = (BYTE)(wc >> 8); pb->buf[i++] = (BYTE)wc; - nc++; -#elif FF_STRF_ENCODE == 1 /* Write a character in UTF-16LE */ - if (hs != 0) { - pb->buf[i++] = (BYTE)hs; - pb->buf[i++] = (BYTE)(hs >> 8); - nc++; +#elif FF_STRF_ENCODE == 3 /* Write it in UTF-8 */ + if (hs != 0) { /* 4-byte */ + nc += 3; + hs = (hs & 0x3FF) + 0x40; + pb->buf[i++] = (BYTE)(0xF0 | hs >> 8); + pb->buf[i++] = (BYTE)(0x80 | (hs >> 2 & 0x3F)); + pb->buf[i++] = (BYTE)(0x80 | (hs & 3) << 4 | (wc >> 6 & 0x0F)); + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } else { + if (wc < 0x80) { /* 1-byte */ + pb->buf[i++] = (BYTE)wc; + } else { + if (wc < 0x800) { /* 2-byte */ + nc += 1; + pb->buf[i++] = (BYTE)(0xC0 | wc >> 6); + } else { /* 3-byte */ + nc += 2; + pb->buf[i++] = (BYTE)(0xE0 | wc >> 12); + pb->buf[i++] = (BYTE)(0x80 | (wc >> 6 & 0x3F)); + } + pb->buf[i++] = (BYTE)(0x80 | (wc & 0x3F)); + } } - pb->buf[i++] = (BYTE)wc; - pb->buf[i++] = (BYTE)(wc >> 8); - nc++; -#else /* Write a character in ANSI/OEM */ +#else /* Write it in ANSI/OEM */ if (hs != 0) return; wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */ if (wc == 0) return;; if (wc >= 0x100) { pb->buf[i++] = (BYTE)(wc >> 8); nc++; } - pb->buf[i++] = (BYTE)wc; nc++; -#endif + pb->buf[i++] = (BYTE)wc; #endif -#else /* ANSI/OEM input */ +#else /* ANSI/OEM input (without re-encode) */ pb->buf[i++] = (BYTE)c; - nc++; #endif if (i >= (int)(sizeof pb->buf) - 4) { /* Write buffered characters to the file */ @@ -6341,7 +6319,7 @@ void putc_bfd ( /* Buffered write with code conversion */ i = (n == (UINT)i) ? 0 : -1; } pb->idx = i; - pb->nchr = nc; + pb->nchr = nc + 1; } @@ -6534,7 +6512,7 @@ FRESULT f_setcp ( ) { static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0}; - static const BYTE *const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; + static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; UINT i; diff --git a/source/ff.h b/source/ff.h index da57ca8..cd90d6d 100644 --- a/source/ff.h +++ b/source/ff.h @@ -1,8 +1,8 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem module R0.13a / +/ FatFs - Generic FAT Filesystem module R0.13b / /-----------------------------------------------------------------------------/ / -/ Copyright (C) 2017, ChaN, all right reserved. +/ Copyright (C) 2018, 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 89352 /* Revision ID */ +#define FF_DEFINED 63463 /* Revision ID */ #ifdef __cplusplus extern "C" { @@ -45,6 +45,12 @@ typedef struct { extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ #endif +#if FF_STR_VOLUME_ID +#ifndef FF_VOLUME_STRS +extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ +#endif +#endif + /* Type of path name strings on FatFs API */ @@ -60,7 +66,11 @@ typedef WCHAR TCHAR; typedef char TCHAR; #define _T(x) u8 ## x #define _TEXT(x) u8 ## x -#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 2) +#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */ +typedef DWORD TCHAR; +#define _T(x) U ## x +#define _TEXT(x) U ## x +#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3) #error Wrong FF_LFN_UNICODE setting #else /* ANSI/OEM code in SBCS/DBCS */ typedef char TCHAR; diff --git a/source/ffconf.h b/source/ffconf.h index 567ddf5..fe5aacd 100644 --- a/source/ffconf.h +++ b/source/ffconf.h @@ -2,7 +2,7 @@ / FatFs - Configuration file /---------------------------------------------------------------------------*/ -#define FFCONF_DEF 89352 /* Revision ID */ +#define FFCONF_DEF 63463 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations @@ -123,6 +123,7 @@ / 0: ANSI/OEM in current CP (TCHAR = char) / 1: Unicode in UTF-16 (TCHAR = WCHAR) / 2: Unicode in UTF-8 (TCHAR = char) +/ 3: Unicode in UTF-32 (TCHAR = DWORD) / / Also behavior of string I/O functions will be affected by this option. / When LFN is not enabled, this option has no effect. */ @@ -168,11 +169,16 @@ #define FF_STR_VOLUME_ID 0 #define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" -/* FF_STR_VOLUME_ID switches string support for volume ID. -/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive -/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each -/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for -/ the drive ID strings are: A-Z and 0-9. */ +/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings. +/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each +/ logical drives. Number of items must not be less than FF_VOLUMES. Valid +/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are +/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is +/ not defined, a user defined volume string table needs to be defined as: +/ +/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... +*/ #define FF_MULTI_PARTITION 0 @@ -226,17 +232,17 @@ #define FF_FS_EXFAT 0 /* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) -/ When enable exFAT, also LFN needs to be enabled. +/ To enable exFAT, also LFN needs to be enabled. / Note that enabling exFAT discards ANSI C (C89) compatibility. */ #define FF_FS_NORTC 0 #define FF_NORTC_MON 1 #define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2017 +#define FF_NORTC_YEAR 2018 /* The option FF_FS_NORTC switches timestamp functiton. If the system does not have / any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable -/ the timestamp function. All objects modified by FatFs will have a fixed timestamp +/ the timestamp function. Every object modified by FatFs will have a fixed timestamp / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be / added to the project to read current time form real-time clock. FF_NORTC_MON, diff --git a/source/ffsystem.c b/source/ffsystem.c index b0170a8..9df330f 100644 --- a/source/ffsystem.c +++ b/source/ffsystem.c @@ -52,7 +52,7 @@ void ff_memfree ( int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ BYTE vol, /* Corresponding volume (logical drive number) */ - FF_SYNC_t *sobj /* Pointer to return the created sync object */ + FF_SYNC_t* sobj /* Pointer to return the created sync object */ ) { /* Win32 */ diff --git a/source/ffunicode.c b/source/ffunicode.c index 901affe..9a5d37e 100644 --- a/source/ffunicode.c +++ b/source/ffunicode.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------*/ -/* Unicode handling functions for FatFs R0.13a */ +/* Unicode handling functions for FatFs R0.13b */ /*------------------------------------------------------------------------*/ /* This module will occupy a huge memory in the .const section when the / / FatFs is configured for LFN with DBCS. If the system has any Unicode / @@ -7,7 +7,7 @@ / that function to avoid silly memory consumption. / /-------------------------------------------------------------------------*/ /* -/ Copyright (C) 2017, ChaN, all right reserved. +/ Copyright (C) 2018, 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 @@ -27,7 +27,7 @@ #if FF_USE_LFN /* This module is blanked when non-LFN configuration */ -#if FF_DEFINED != 89352 /* Revision ID */ +#if FF_DEFINED != 63463 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -40,8 +40,7 @@ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */ -static -const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */ +static const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */ 0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180, 0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6, 0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE, @@ -968,8 +967,7 @@ const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */ 0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0 }; -static -const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */ +static const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */ 0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68, 0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70, 0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78, @@ -1898,8 +1896,7 @@ const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */ #endif #if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */ -static -const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */ +static const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */ 0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4, 0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE, 0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9, @@ -4627,8 +4624,7 @@ const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */ 0, 0 }; -static -const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */ +static const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */ 0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17, 0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F, 0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42, @@ -7358,8 +7354,7 @@ const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */ #endif #if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */ -static -const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */ +static const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */ 0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6, 0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6, 0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF, @@ -9494,8 +9489,7 @@ const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */ 0, 0 }; -static -const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */ +static const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */ 0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E, 0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25, 0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32, @@ -11632,8 +11626,7 @@ const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */ #endif #if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */ -static -const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */ +static const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */ 0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE, 0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346, 0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E, @@ -13324,8 +13317,7 @@ const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */ 0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0 }; -static -const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */ +static const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */ 0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A, 0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52, 0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31, @@ -15018,8 +15010,7 @@ const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */ #endif #if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0 -static -const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ +static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -15031,8 +15022,7 @@ const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0 -static -const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ +static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, @@ -15044,8 +15034,7 @@ const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0 -static -const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ +static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, @@ -15057,8 +15046,7 @@ const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0 -static -const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ +static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, @@ -15070,8 +15058,7 @@ const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0 -static -const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ +static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, @@ -15083,8 +15070,7 @@ const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0 -static -const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ +static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -15096,8 +15082,7 @@ const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0 -static -const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ +static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, @@ -15109,8 +15094,7 @@ const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0 -static -const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ +static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, @@ -15122,8 +15106,7 @@ const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0 -static -const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ +static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -15135,8 +15118,7 @@ const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0 -static -const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ +static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -15148,8 +15130,7 @@ const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0 -static -const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ +static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -15161,8 +15142,7 @@ const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0 -static -const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ +static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, @@ -15174,8 +15154,7 @@ const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0 -static -const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ +static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, @@ -15187,8 +15166,7 @@ const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table * }; #endif #if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0 -static -const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ +static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, @@ -15200,8 +15178,7 @@ const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0 -static -const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ +static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, @@ -15213,8 +15190,7 @@ const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0 -static -const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ +static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, @@ -15226,8 +15202,7 @@ const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ }; #endif #if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0 -static -const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ +static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, @@ -15261,7 +15236,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ c = (WCHAR)uni; } else { /* Non-ASCII */ - if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it a valid code? */ + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ for (c = 0; c < 0x80 && uni != p[c]; c++) ; c = (c + 0x80) & 0xFF; } @@ -15308,30 +15283,28 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ { const WCHAR *p; WCHAR c = 0, uc; - UINT i, n, li, hi; + UINT i = 0, n, li, hi; if (uni < 0x80) { /* ASCII? */ c = (WCHAR)uni; } else { /* Non-ASCII */ - if (uni < 0x10000) { /* Is it in BMP? */ - if (cp == FF_CODE_PAGE) { /* Is it a valid code? */ - uc = (WCHAR)uni; - p = CVTBL(uni2oem, FF_CODE_PAGE); - hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; - li = 0; - for (n = 16; n; n--) { - i = li + (hi - li) / 2; - if (uc == p[i * 2]) break; - if (uc > p[i * 2]) { - li = i; - } else { - hi = i; - } + if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */ + uc = (WCHAR)uni; + p = CVTBL(uni2oem, FF_CODE_PAGE); + hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (uc == p[i * 2]) break; + if (uc > p[i * 2]) { + li = i; + } else { + hi = i; } - if (n != 0) c = p[i * 2 + 1]; } + if (n != 0) c = p[i * 2 + 1]; } } @@ -15346,14 +15319,14 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ { const WCHAR *p; WCHAR c = 0; - UINT i, n, li, hi; + UINT i = 0, n, li, hi; if (oem < 0x80) { /* ASCII? */ c = oem; } else { /* Extended char */ - if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + if (cp == FF_CODE_PAGE) { /* Is it valid code page? */ p = CVTBL(oem2uni, FF_CODE_PAGE); hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1; li = 0; @@ -15383,7 +15356,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ #if FF_CODE_PAGE == 0 static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0}; -static const WCHAR *const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; +static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ @@ -15404,20 +15377,20 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ uc = (WCHAR)uni; p = 0; if (cp < 900) { /* SBCS */ - for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */ p = cp_table[i]; - if (p) { /* Is it a valid CP ? */ + if (p) { /* Is it valid code page ? */ for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */ c = (c + 0x80) & 0xFF; } } else { /* DBCS */ - switch (cp) { + switch (cp) { /* Get conversion table */ case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break; case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break; case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break; case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break; } - if (p) { /* Is it a valid code page? */ + if (p) { /* Is it valid code page? */ li = 0; for (n = 16; n; n--) { /* Find OEM code */ i = li + (hi - li) / 2; @@ -15496,50 +15469,90 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ DWORD uni /* Unicode code point to be up-converted */ ) { - /* Compressed upper conversion table */ - static const WORD cvt1[] = { /* U+0000 - U+0FFF */ + const WORD *p; + WORD uc, bc, nc, cmd; + static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ /* Basic Latin */ 0x0061,0x031A, /* Latin-1 Supplement */ - 0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178, + 0x00E0,0x0317, + 0x00F8,0x0307, + 0x00FF,0x0001,0x0178, /* Latin Extended-A */ - 0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106, + 0x0100,0x0130, + 0x0132,0x0106, + 0x0139,0x0110, + 0x014A,0x012E, + 0x0179,0x0106, /* Latin Extended-B */ 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA, - 0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128, - 0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A, + 0x01CD,0x0110, + 0x01DD,0x0001,0x018E, + 0x01DE,0x0112, + 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, + 0x01F8,0x0128, + 0x0222,0x0112, + 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, + 0x0246,0x010A, /* IPA Extensions */ 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7, /* Greek, Coptic */ - 0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311, - 0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118, + 0x037B,0x0003,0x03FD,0x03FE,0x03FF, + 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, + 0x03B1,0x0311, + 0x03C2,0x0002,0x03A3,0x03A3, + 0x03C4,0x0308, + 0x03CC,0x0003,0x038C,0x038E,0x038F, + 0x03D8,0x0118, 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, /* Cyrillic */ - 0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144, + 0x0430,0x0320, + 0x0450,0x0710, + 0x0460,0x0122, + 0x048A,0x0136, + 0x04C1,0x010E, + 0x04CF,0x0001,0x04C0, + 0x04D0,0x0144, /* Armenian */ 0x0561,0x0426, - 0x0000 + 0x0000 /* EOT */ }; - static const WORD cvt2[] = { /* U+1000 - U+FFFF */ + static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */ /* Phonetic Extensions */ 0x1D7D,0x0001,0x2C63, /* Latin Extended Additional */ - 0x1E00,0x0196, 0x1EA0,0x015A, + 0x1E00,0x0196, + 0x1EA0,0x015A, /* Greek Extended */ - 0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606, - 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608, + 0x1F00,0x0608, + 0x1F10,0x0606, + 0x1F20,0x0608, + 0x1F30,0x0608, + 0x1F40,0x0606, + 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, + 0x1F60,0x0608, 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, - 0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, - 0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF3,0x0001,0x1FFC, + 0x1F80,0x0608, + 0x1F90,0x0608, + 0x1FA0,0x0608, + 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, + 0x1FCC,0x0001,0x1FC3, + 0x1FD0,0x0602, + 0x1FE0,0x0602, + 0x1FE5,0x0001,0x1FEC, + 0x1FF3,0x0001,0x1FFC, /* Letterlike Symbols */ 0x214E,0x0001,0x2132, /* Number forms */ - 0x2170,0x0210, 0x2184,0x0001,0x2183, + 0x2170,0x0210, + 0x2184,0x0001,0x2183, /* Enclosed Alphanumerics */ - 0x24D0,0x051A, 0x2C30,0x042F, + 0x24D0,0x051A, + 0x2C30,0x042F, /* Latin Extended-C */ - 0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102, + 0x2C60,0x0102, + 0x2C67,0x0106, 0x2C75,0x0102, /* Coptic */ 0x2C80,0x0164, /* Georgian Supplement */ @@ -15547,18 +15560,16 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ /* Full-width */ 0xFF41,0x031A, - 0x0000 + 0x0000 /* EOT */ }; - const WORD *p; - WORD uc, bc, nc, cmd; if (uni < 0x10000) { /* Is it in BMP? */ uc = (WORD)uni; p = uc < 0x1000 ? cvt1 : cvt2; for (;;) { - bc = *p++; /* Get block base */ - if (!bc || uc < bc) break; + bc = *p++; /* Get the block base */ + if (bc == 0 || uc < bc) break; /* Not matched? */ nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ if (uc < bc + nc) { /* In the block? */ switch (cmd) { @@ -15574,7 +15585,7 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ } break; } - if (!cmd) p += nc; + if (cmd == 0) p += nc; /* Skip table if needed */ } uni = uc; } diff --git a/source/integer.h b/source/integer.h index 4fcf5c4..b3c70ca 100644 --- a/source/integer.h +++ b/source/integer.h @@ -8,10 +8,8 @@ #ifdef _WIN32 /* FatFs development platform */ #include -#include typedef unsigned __int64 QWORD; - #else /* Embedded platform */ /* These types MUST be 16-bit or 32-bit */