diff --git a/doc/00index_e.html b/doc/00index_e.html index fb9cb5d..c32b9da 100644 --- a/doc/00index_e.html +++ b/doc/00index_e.html @@ -3,6 +3,8 @@ + + ELM - FAT File System Module @@ -14,7 +16,7 @@
layer -

FatFs is a generic file system module to implement the FAT file system to small embedded systems. The FatFs is written in compliance with ANSI C, therefore it is independent of hardware architecture. It can be incorporated into cheap microcontrollers, such as 8051, PIC, AVR, SH, Z80, H8, ARM and etc..., without any change.

+

FatFs is a generic FAT file system module for small embedded systems. The FatFs is written in compliance with ANSI C and completely separated from the disk I/O layer. Therefore it is independent of hardware architecture. It can be incorporated into cheap microcontrollers, such as 8051, PIC, AVR, SH, Z80, H8, ARM and etc..., without any change. Petit FatFs module is also available here.

Features

Disk I/O Interface

-

Since the FatFs module is completely separated from disk I/O layer, it requires following functions to lower layer to read/write physical disk and to get current time. The low level disk I/O module is not a part of FatFs module and it must be provided by user. The sample drivers are also available in the resources.

+

Since the FatFs module is completely separated from disk I/O layer, it requires following functions to lower layer to read/write the physical disk and to get current time. The low level disk I/O module is not a part of FatFs module and it must be provided by user. The sample drivers are also available in the resources.

diff --git a/doc/00index_j.html b/doc/00index_j.html index a6ec6eb..7c64b97 100644 --- a/doc/00index_j.html +++ b/doc/00index_j.html @@ -3,6 +3,8 @@ + + ELM - 汎用FATファイルシステム・モジュール @@ -42,7 +44,7 @@
  • f_close - ファイルのクローズ
  • f_read - ファイルの読み込み
  • f_write - ファイルの書き込み
  • -
  • f_lseek - ファイルR/Wポインタの移動
  • +
  • f_lseek - R/Wポインタの移動, ファイル・サイズの拡張
  • f_truncate - ファイル・サイズの切り詰め
  • f_sync - キャッシュされたデータのフラッシュ
  • f_opendir - ディレクトリのオープン
  • @@ -55,6 +57,8 @@
  • f_utime - ファイル/ディレクトリのタイムスタンプの変更
  • f_rename - ファイル/ディレクトリの名前変更・移動
  • f_mkfs - ディスクのフォーマット
  • +
  • f_chdir - カレント・ディレクトリの変更
  • +
  • f_chdrive - カレント・ドライブの変更
  • f_forward - ファイル・データをストリーム関数に直接転送する
  • f_gets - 文字列の読み込み
  • f_putc - 文字の書き込み
  • @@ -82,15 +86,14 @@

    資料

    FatFsモジュールはフリー・ソフトウェアとして教育・研究・開発用に公開しています。どのような利用目的(個人・非商用・商用)でも使用・改変・配布について一切の制限はありませんが、全て利用者の責任の下での利用とします。

    diff --git a/doc/en/appnote.html b/doc/en/appnote.html index ffe3aaa..70f4113 100644 --- a/doc/en/appnote.html +++ b/doc/en/appnote.html @@ -24,15 +24,15 @@ The FatFs module assumes that size of char/short/long are 8/16/32-bit and int is
    -

    Memory Usage (R0.07)

    +

    Memory Usage (R0.07c)

    - + - - - - + + + + @@ -46,6 +46,8 @@ _USE_MKFS 0 (Disable f_mkfs function) _USE_FORWARD 0 (Disable f_forward function) _CODE_PAGE 932 (Japanese Shift-JIS) _USE_LFN 0 (Disable LFN) +_MAX_SS 512 (Single sector size) +_FS_RPATH 0 (Disable relative path) _MULTI_PARTITION 0 (Single partition per drive) _FS_REENTRANT 0 (Disable reentrancy) @@ -55,45 +57,47 @@ _FS_REENTRANT 0 (Disable reentrancy)

    Module Size Reduction

    Follwing table shows which function is removed by configuration options for the module size reduction.

    AVRH8/300HPICTLCS-870/CV850ESSH2ARM7TDMIIA-32
    Compilergcc(WinAVR)CH38gcc(C30)CC870CCA850SHCgcc(WinARM)MSC
    CompilerWinAVR(gcc)CH38C30(gcc)CC870CCA850SHCWinARM(gcc)MSC
    _WORD_ACCESS10011001
    ROM (Full, R/W)1113610356108381516776828654106287232
    ROM (Min, R/W)70726696700798004634557065644647
    ROM (Full, R/O)52184626494967863528382646763267
    ROM (Min, R/O)36263418353649412558287432722397
    ROM (Full, R/W)1196210433107531515377478707105847337
    ROM (Min, R/W)74666799677299064901559965484787
    ROM (Full, R/O)54004687480467443539379946763380
    ROM (Min, R/O)38043527342150402561286732762533
    RAM (Static)D*2 + 2D*4 + 2D*2 + 2D*2 + 2D*4 + 2D*4 + 2D*4 + 2D*4 + 2
    RAM (Dynamic)
    (_FS_TINY == 0)
    D*560 +
    F*544
    D*560 +
    F*550
    D*560 +
    F*544
    D*560 +
    F*550
    D*560 +
    F*550
    D*560 +
    F*550
    D*560 +
    F*550
    RAM (Dynamic)
    (_FS_TINY == 1)
    D*560 +
    F*32
    D*560 +
    F*36
    D*560 +
    F*32
    D*560 +
    F*32
    D*560 +
    F*36
    D*560 +
    F*36
    D*560 +
    F*36
    D*560 +
    F*36
    - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Function_FS_MINIMIZE_FS_READONLY_USE_STRFUNC_USE_MKFS_USE_FORWARD
    1231000
    f_mount
    f_open
    f_close
    f_read
    f_writex
    f_syncx
    f_lseekx
    f_opendirxx
    f_readdirxx
    f_statxxx
    f_getfreexxxx
    f_truncatexxxx
    f_unlinkxxxx
    f_mkdirxxxx
    f_chmodxxxx
    f_utimexxxx
    f_renamexxxx
    f_mkfsxx
    f_forwardx
    f_putcxx
    f_putsxx
    f_printfxx
    f_getsx
    Function_FS_MINIMIZE_FS_READONLY_USE_STRFUNC_FS_RPATH_USE_MKFS_USE_FORWARD
    12310000
    f_mount
    f_open
    f_close
    f_read
    f_writex
    f_syncx
    f_lseekx
    f_opendirxx
    f_readdirxx
    f_statxxx
    f_getfreexxxx
    f_truncatexxxx
    f_unlinkxxxx
    f_mkdirxxxx
    f_chmodxxxx
    f_utimexxxx
    f_renamexxxx
    f_chdirx
    f_chdrivex
    f_mkfsxx
    f_forwardx
    f_putcxx
    f_putsxx
    f_printfxx
    f_getsx

    Long File Name

    -

    The FatFs module supports long file name (LFN) from revision 0.07. The two different file names, SFN and LFN, of a file is transparent in the file functions except for f_readdir function. To enable LFN feature, set _USE_LFN to 1 or 2, and add an OEM-Unicode bidirectional code conversion function ff_convert to the project. This function is available in cc*.c. The LFN feature requiers a certain working buffer in addition. The buffer size can be configured by _MAX_LFN corresponding to the available memory size. The size of long file name will reach up to 255 characters so that the _MAX_LFN should be set to 255 for full featured LFN operation. When the size of working buffer is insufficient for the given file name, the file function will fail with FR_INVALID_NAME. When enable the LFN feature with re-entrant feature, _USE_LFN must be set to 2. In this case, the file funciton allocates the working buffer on the stack. The working buffer occupies _MAX_LFN * 2 + 1 bytes so that the caller's stack must be a sufficient size considering the working buffer.

    +

    The FatFs module supports long file name (LFN) from revision 0.07. The two different file names, SFN and LFN, of a file is transparent in the file functions except for f_readdir function. To enable LFN feature, set _USE_LFN to 1 or 2, and add a Unicode code conversion function ff_convert and ff_wtoupper to the project. This function is available in cc*.c. The LFN feature requiers a certain working buffer in addition. The buffer size can be configured by _MAX_LFN corresponding to the available memory size. The size of long file name will reach up to 255 characters so that the _MAX_LFN should be set to 255 for full featured LFN operation. When the size of working buffer is insufficient for the given file name, the file function will fail with FR_INVALID_NAME. When enable the LFN feature with re-entrant feature, _USE_LFN must be set to 2. In this case, the file funciton allocates the working buffer on the stack. The working buffer occupies (_MAX_LFN + 1) * 2 bytes so that the caller's stack must be a sufficient size considering the working buffer.

    - + - - - - - + + + + +
    LFN cfg on ARM7DMILFN cfg on ARM7
    Code pageROM size [bytes]
    SBCS+4719
    932(Shift-JIS)+63755
    936(GBK)+178943
    949(Korean)+141003
    950(Big5)+112631
    SBCS+3721
    932(Shift-JIS)+62609
    936(GBK)+177797
    949(Korean)+139857
    950(Big5)+111497

    When the LFN feature is enabled, the module size will be increased depends on the selected code page. Right table shows the difference in module size when LFN is enabled with some code pages. We are the Japanese, Chinese and Korean have tens of thousands of characters. Unfortunately, it requires a huge OEM-Unicode bidirectional conversion table and the module size will be drastically increased that shown in the table. As the result, the FatFs with LFN will not able to be implemented to most 8-bit microcontrollers including AVR. This is the reason why I had not been interested in implementing the LFN feature for a long time :-)

    Note that the LFN feature on the FAT file system is a patent of Microsoft Corporation. When enable it on the commercial products, a license from Microsoft may be required depends on the final destination.

    @@ -152,6 +156,11 @@ Figure 5. Minimized critical section

    Each case does not affect the files that not in write mode open. To minimize risk of data loss, the critical section can be minimized like shown in Figure 5 by minimizing the time that file is opened in write mode or using f_sync function properly.

    +
    +

    Unicode API

    +

    FatFs supports to switch the character encoding to Unicode on the API. For more information, refer to the description in the file name.

    +
    +

    Return

    diff --git a/doc/en/chdir.html b/doc/en/chdir.html new file mode 100644 index 0000000..0c7b2b8 --- /dev/null +++ b/doc/en/chdir.html @@ -0,0 +1,81 @@ + + + + + + + +FatFs - f_chdir + + + + +
    +

    f_chdir

    +

    The f_chdir function changes the current directory of a drive.

    +
    +FRESULT f_chdir (
    +  const XCHAR* Path /* Pointer to the path name */
    +);
    +
    +
    + +
    +

    Parameters

    +
    +
    Path
    +
    Pointer to the null-terminated string that specifies a directory to go.
    +
    +
    + + +
    +

    Return Values

    +
    +
    FR_OK (0)
    +
    The function succeeded.
    +
    FR_NO_PATH
    +
    Could not find the path.
    +
    FR_INVALID_NAME
    +
    The path name is invalid.
    +
    FR_INVALID_DRIVE
    +
    The drive number is invalid.
    +
    FR_NOT_READY
    +
    The disk drive cannot work due to no medium in the drive or any other reason.
    +
    FR_DISK_ERR
    +
    The function failed due to an error in the disk function.
    +
    FR_INT_ERR
    +
    The function failed due to a wrong FAT structure or an internal error.
    +
    FR_NOT_ENABLED
    +
    The logical drive has no work area.
    +
    FR_NO_FILESYSTEM
    +
    There is no valid FAT partition on the disk.
    +
    +
    + + +
    +

    Description

    +

    The f_chdir function changes the current directory of the logical drive. The current directory of a drive is initialized to the root directory when the drive is auto-mounted. Note that the current directory is retained in the each file system object so that it also affects other tasks that using the drive. This function is available when _FS_RPATH == 1.

    +
    + + +
    +

    Example

    +
    +    // Change current direcoty of the current drive (dir1 under root dir)
    +    f_chdir("/dir1");
    +
    +    // Change current direcoty of drive 2 (parent dir)
    +    f_chdir("2:..");
    +
    +
    + +
    +

    References

    +

    f_chdrive

    +
    + +

    Return

    + + diff --git a/doc/en/chdrive.html b/doc/en/chdrive.html new file mode 100644 index 0000000..4d70e89 --- /dev/null +++ b/doc/en/chdrive.html @@ -0,0 +1,55 @@ + + + + + + + +FatFs - f_chdrive + + + + +
    +

    f_chdrive

    +

    The f_chdrive function changes the current drive.

    +
    +FRESULT f_chdrive (
    +  BYTE Drive /* Logical drive number */
    +);
    +
    +
    + +
    +

    Parameters

    +
    +
    Drive
    +
    Specifies the logical drive number to be set as the current drive.
    +
    +
    + + +
    +

    Return Values

    +
    +
    FR_OK (0)
    +
    The function succeeded.
    +
    FR_INVALID_DRIVE
    +
    The drive number is invalid.
    +
    +
    + + +
    +

    Description

    +

    The f_chdrive function changes the current drive. The initial value of the current drive number is 0. Note that the current drive is retained in a static variable so that it also affects other tasks that using the file functions. This function is available when _FS_RPATH == 1.

    +
    + +
    +

    References

    +

    f_chdir

    +
    + +

    Return

    + + diff --git a/doc/en/chmod.html b/doc/en/chmod.html index 9e6c161..76eb187 100644 --- a/doc/en/chmod.html +++ b/doc/en/chmod.html @@ -15,9 +15,9 @@

    The f_chmod function changes the attribute of a file or directory.

     FRESULT f_chmod (
    -  const char* FileName, /* Pointer to the file or directory */
    -  BYTE Attribute,       /* Attribute flags */
    -  BYTE AttributeMask    /* Attribute masks */
    +  const XCHAR* FileName, /* Pointer to the file or directory */
    +  BYTE Attribute,        /* Attribute flags */
    +  BYTE AttributeMask     /* Attribute masks */
     );
     
    diff --git a/doc/en/dinit.html b/doc/en/dinit.html index dc2e1e4..e777500 100644 --- a/doc/en/dinit.html +++ b/doc/en/dinit.html @@ -32,7 +32,7 @@ DSTATUS disk_initialize (

    Return Values

    This function returns a disk status as the result. For details of the disk status, refer to the disk_status function.

    -

    This function is called from volume mount process in the FatFs module to manage the media change. Application module should not use this function during FatFs module is active.

    +

    This function is called from volume mount process in the FatFs module to manage the media change. Application program must not call this function while FatFs module is active, or FAT structure on the drive may be collapted.

    diff --git a/doc/en/filename.html b/doc/en/filename.html index fb69d20..b38bbca 100644 --- a/doc/en/filename.html +++ b/doc/en/filename.html @@ -1,40 +1,50 @@ - + -FatFs - File and Path name on the FatFs module +FatFs - Path Names
    -

    File and Path name on the FatFs module

    -

    The format of file and path name on the FatFs module is similer to MS-DOS. However it does not have a concept of current directory like OS oriented file system. All objects on the drive are always specified in full path name from the root directory.

    +

    Format of the path names

    +

    The path name format on the FatFs module is similer to MS-DOS as follows.

    -
      "[drive#:][/]directory/file"
    -
    - "file1.txt"           A file on the drive 0
    - "/file1.txt"          (same as above)
    - "dir1/dir2/file1.txt" A file on the drive 0
    - "2:dir3/file2.txt"    A file on the drive 2
    - "2:/dir5"             A directory on the drive 2
    - ""                    The root directory on the drive 0
    - "/"                   (same as above)
    - "2:"                  The root directory on the drive 2
    -
     
    -

    The FatFs module supports long file name and 8.3 format file name. The long file name can be handled when _USE_LFN option is selected. The sub directories are separated with a / or \. Heading separator is ignored and it may be exist or omitted.

    -

    The logical drive number is specified in a numeral with a colon. When the drive number is omitted, it is assumed as default drive (0:).

    +

    The FatFs module supports long file name and 8.3 format file name. The long file name can be handled in LFN configuration (_USE_LFN == 1). The path names are input/output in local code (SBCS/MBCS) or Unicode string depends on the configuration options. The sub directories are separated with a / or \. The logical drive number is specified in a numeral with a colon. When the drive number is omitted, it is assumed as default drive (0 or current drive).

    +

    In default configuration (_FS_RPATH == 0), it does not have a concept of current directory like OS oriented file system. All objects on the volume are always specified in full path name following from the root directory. Dot names are not available. Heading separator is ignored and it can be exist or omitted. The default drive number is fixed to 0.

    +

    When relative path feature is enabled (_FS_RPATH == 1), specified path is followed from the root directory if a heading separator is exist. If not, the path is followed from the current directory set with f_chdir function. Dot names are also available for the path name. The default drive number is the current drive number set with f_chdrive function.

    + + + + + + + + + + + + + +
    Path name_FS_RPATH == 0_FS_RPATH == 1
    file.txtA file in the root directory on the drive 0A file in the current directory on the current drive
    /file.txtA file in the root directory on the drive 0A file in the root directory on the current drive
    The root directory on the drive 0The current directory on the current drive
    2:The root directory on the drive 2The current directory on the drive 2
    2:file.txtA file in the root directory on the drive 2A file in the current directory on the drive 2
    2:/The root directory on the drive 2The root directory on the drive 2
    ../file.txtInvalid nameA file in the parent directory
    .Invalid nameThis directory
    ..Invalid nameParent directory of the current directory
    dir1/..Invalid nameThe current directory
    /..Invalid nameInvalid name (Cannot use dot names at the root directory)


    -

    Correspondence between logical/physical drive

    -

    In default, the FatFs module has work areas that called file system object for each logical drive. The logical drive is bound to the physical drive that has same drive number, and the first partition is mounted. When _MULTI_PARTITION is specified in configuration option, each individual logical drive can be bound to any physical drive/partition. In this case, a drive number resolution table must be defined as follows:

    +

    Unicode API

    +

    The type of arguments that specifies the file names are defined as XCHAR, which is the alias of char in default. The code set of the file name string is the local code set that specifid by _CODE_PAGE. When _LFN_UNICODE is set to 1 with LFN configuration, the type of the XCHAR is switched to unsigned short (wide character) to support Unicode. In this case, the LFN feature is fully supported and the Unicode specific characters, such as 笙・, 笘ュ and 笶カ, can also be used.

    +
    + +


    +
    +

    Correspondence between logical and physical drives

    +

    The FatFs module has work areas that called file system object for each volume (logical drive). In default, the logical drive is bound to the physical drive that has same drive number, and the first partition is mounted. When _MULTI_PARTITION == 1 is specified in configuration option, each individual logical drive can be bound to any physical drive/partition. In this case, a drive number resolution table must be defined as follows:

     Example: Logical drive 0-2 are assigned to three pri-partitions on the physical drive 0 (fixed disk)
              Logical drive 3 is assigned to physical drive 1 (removable disk)
    @@ -49,8 +59,8 @@ const PARTITION Drives[] = {
     

    There are some consideration when use _MULTI_PARTITION configuration.

    • Only pri-partition (0-3) can be mounted.
    • -
    • When the physical drive have no partition table (super floppy format), the partition number is ignored.
    • -
    • The physical drive that has two or more logical drives must be fixed drive.
    • +
    • When the physical drive has no partition table (SFD format), the partition number is ignored.
    • +
    • The physical drive that has two or more logical drives must not be removable drive.
    diff --git a/doc/en/getfree.html b/doc/en/getfree.html index 03ab0ec..6477097 100644 --- a/doc/en/getfree.html +++ b/doc/en/getfree.html @@ -15,7 +15,7 @@

    The f_getfree function gets number of the free clusters.

     FRESULT f_getfree (
    -  const char* Path,         /* Root directory of the drive */
    +  const XCHAR* Path,        /* Root directory of the drive */
       DWORD* Clusters,          /* Pointer to the variable to store number of free clusters */
       FATFS** FileSystemObject  /* Pointer to pointer to file system object */
     );
    @@ -26,7 +26,7 @@ FRESULT f_getfree (
     

    Parameters

    Path
    -
    Pinter to the null-terminated string that specifies the root directory of the logical drive. Always specify a null-string for Tiny-FatFs.
    +
    Pinter to the null-terminated string that specifies the root directory of the logical drive.
    Clusters
    Pointer to the DWORD variable to store number of free clusters.
    FileSystemObject
    @@ -58,7 +58,7 @@ FRESULT f_getfree (

    Descriptions

    -

    The f_getfree function gets number of free clusters on the drive. The member csize in the file system object is refreting number of sectors per cluster, so that the free space in unit of sector can be calcurated with this. When FSInfo structure on FAT32 volume is not in sync, this function can return an incorrect free cluster count.

    +

    The f_getfree function gets number of free clusters on the drive. The member csize in the file system object is refrecting number of sectors per cluster, so that the free space in unit of sector can be calcurated with this. When FSInfo structure on FAT32 volume is not in sync, this function can return an incorrect free cluster count.

    This function is not supported in read-only configuration and minimization level of >= 1.

    @@ -67,18 +67,21 @@ FRESULT f_getfree (

    Example

         FATFS *fs;
    -    DWORD clust;
    +    DWORD fre_clust, fre_sect, tot_sect;
     
     
    -    // Get free clusters
    -    res = f_getfree("", &clust, &fs);
    +    // Get drive information and free clusters
    +    res = f_getfree("/", &fre_clust, &fs);
         if (res) die(res);
     
    -    // Get free space
    -    printf("%lu KB total disk space.\n"
    -           "%lu KB available on the disk.\n",
    -           (DWORD)(fs->max_clust - 2) * fs->csize / 2,
    -           clust * fs->csize / 2);
    +    // Get total sectors and free sectors
    +    tot_sect = (fs->max_clust - 2) * fs->csize;
    +    fre_sect = fre_clust * fs->csize;
    +
    +    // Print free space in unit of KB (assuming 512B/sector)
    +    printf("%lu KB total drive space.\n"
    +           "%lu KB available.\n",
    +           fre_sect / 2, tot_sect / 2);
     
    diff --git a/doc/en/lseek.html b/doc/en/lseek.html index 641800e..a7ee1b9 100644 --- a/doc/en/lseek.html +++ b/doc/en/lseek.html @@ -28,7 +28,7 @@ FRESULT f_lseek (
    FileObject
    Pointer to the open file object.
    Offset
    -
    Number of bytes where from start of file
    +
    Number of bytes where from start of the file
    @@ -66,28 +66,28 @@ FRESULT f_lseek ( // Move to offset of 5000 from top of the file. res = f_lseek(&file, 5000); + // Move to end of the file to append data + res = f_lseek(&file, file.fsize); + // Forward 3000 bytes res = f_lseek(&file, file.fptr + 3000); // Rewind 2000 bytes (take care on overflow) res = f_lseek(&file, file.fptr - 2000); - - // Move to end of the file to append data - res = f_lseek(&file, file.fsize);
    -    // Cluster pre-allocation (to prevent data overrun on streaming write)
    +    // Cluster pre-allocation (to prevent buffer overrun on streaming write)
     
         res = f_open(&file, recfile, FA_CREATE_NEW | FA_WRITE); // Create a file
     
    -    res = f_lseek(&file, PRE_SIZE);    // Pre-allocate clusters
    +    res = f_lseek(&file, PRE_SIZE);        // Pre-allocate clusters
         if (res || file.fptr != PRE_SIZE) .... // Check if the file is extended corrctly
     
    -    res = f_lseek(&file, DATA_START);  // Record data stream without cluster allocation delay
    +    res = f_lseek(&file, DATA_START);      // Record data stream without cluster allocation delay
         ...
     
    -    res = f_truncate(&file);           // Truncate unused area
    -    res = f_lseek(&file, 0);           // Put file header
    +    res = f_truncate(&file);               // Truncate unused area
    +    res = f_lseek(&file, 0);               // Put file header
         ...
     
         res = f_close(&file);
    diff --git a/doc/en/mkdir.html b/doc/en/mkdir.html
    index e586bf3..a841b1e 100644
    --- a/doc/en/mkdir.html
    +++ b/doc/en/mkdir.html
    @@ -15,7 +15,7 @@
     

    The f_mkdir function creates a new directory.

     FRESULT f_mkdir (
    -  const char* DirName /* Pointer to the directory name */
    +  const XCHAR* DirName /* Pointer to the directory name */
     );
     
    diff --git a/doc/en/mountdrv.html b/doc/en/mountdrv.html deleted file mode 100644 index bbfc3a3..0000000 --- a/doc/en/mountdrv.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - -FatFs - f_mountdrv - - - - -
    -

    f_mountdrv

    -

    The f_mountdrv forces the partition mounted.

    -
    -FRESULT f_mountdrv (void);
    -
    -
    - -
    -

    Return Values

    -
    -
    FR_OK (0)
    -
    The function succeeded.
    -
    FR_NOT_READY
    -
    The disk drive cannot work due to no medium in the drive or any other reason.
    -
    FR_RW_ERROR
    -
    Any error occured in low level disk I/O.
    -
    FR_NOT_ENABLED
    -
    FatFs module is not enabled.
    -
    FR_NO_FILESYSTEM
    -
    There is no valid FAT partition on the disk.
    -
    -
    - - -
    -

    Description

    -

    The f_mountdrv forces the partition mounted (initializes FATFS structure). The file system is initialized automatically in accordance with the necessity when any file function is called. This function should not be used except for recovering FR_INCORRECT_DISK_CHANGE error. Using this function, while any file is opened, can destroy the file system.

    -

    In this function, following processes are executed.


    - -
    - - -
    -

    References

    -

    FATFS

    -
    - -

    Return

    - - diff --git a/doc/en/open.html b/doc/en/open.html index 6df87f0..c8c22fe 100644 --- a/doc/en/open.html +++ b/doc/en/open.html @@ -15,9 +15,9 @@

    The f_open function creates a file object to be used to access the file.

     FRESULT f_open (
    -  FIL* FileObject,      /* Pointer to the blank file object structure */
    -  const char* FileName, /* Pointer to the file neme */
    -  BYTE ModeFlags        /* Mode flags */
    +  FIL* FileObject,       /* Pointer to the blank file object structure */
    +  const XCHAR* FileName, /* Pointer to the file neme */
    +  BYTE ModeFlags         /* Mode flags */
     );
     
    @@ -83,7 +83,7 @@ FRESULT f_open (

    Description

    -

    The created file object is used for subsequent calls to refer to the file. When close an open file object, use f_close function. If modified file is not closed, the file may be collapsed.

    +

    The created file object is used for subsequent calls to refer to the file. When close an open file object, use f_close function. If the modified file is not closed, the file may be collapsed.

    Before using any file function, a work area (file system object) must be given to the logical drive with f_mount function. All file functions can work after this procedure.

    The mode flags, FA_WRITE, FA_CREATE_ALWAYS, FA_CREATE_NEW, FA_OPEN_ALWAYS, are not available in read-only configuration.

    @@ -92,24 +92,25 @@ FRESULT f_open (

    Example (File Copy)

    -void main ()
    +void main (void)
     {
    -    FATFS fs;            // Work area (file system object) for logical drive
    +    FATFS fs[2];         // Work area (file system object) for logical drives
         FIL fsrc, fdst;      // file objects
         BYTE buffer[4096];   // file copy buffer
         FRESULT res;         // FatFs function common result code
         UINT br, bw;         // File R/W count
     
     
    -    // Register a work area for logical drive 0
    -    f_mount(0, &fs);
    +    // Register work area for logical drives
    +    f_mount(0, &fs[0]);
    +    f_mount(1, &fs[1]);
     
    -    // Open source file
    -    res = f_open(&fsrc, "srcfile.dat", FA_OPEN_EXISTING | FA_READ);
    +    // Open source file on the drive 1
    +    res = f_open(&fsrc, "1:srcfile.dat", FA_OPEN_EXISTING | FA_READ);
         if (res) die(res);
     
    -    // Create destination file
    -    res = f_open(&fdst, "dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE);
    +    // Create destination file on the drive 0
    +    res = f_open(&fdst, "0:dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE);
         if (res) die(res);
     
         // Copy source to destination
    @@ -124,8 +125,9 @@ void main ()
         f_close(&fsrc);
         f_close(&fdst);
     
    -    // Unregister a work area before discard it
    +    // Unregister work area before discard it
         f_mount(0, NULL);
    +    f_mount(1, NULL);
     }
     
    diff --git a/doc/en/opendir.html b/doc/en/opendir.html index 8ce408f..a4c0e3e 100644 --- a/doc/en/opendir.html +++ b/doc/en/opendir.html @@ -15,8 +15,8 @@

    The f_opendir function opens a directory.

     FRESULT f_opendir (
    -  DIR* DirObject,      /* Pointer to the blank directory object structure */
    -  const char* DirName  /* Pointer to the directory name */
    +  DIR* DirObject,       /* Pointer to the blank directory object structure */
    +  const XCHAR* DirName  /* Pointer to the directory name */
     );
     
    diff --git a/doc/en/read.html b/doc/en/read.html index 61042c3..aa37c20 100644 --- a/doc/en/read.html +++ b/doc/en/read.html @@ -33,7 +33,7 @@ FRESULT f_read (
    ByteToRead
    Number of bytes to read in range of UINT.
    ByteRead
    -
    Pointer to the UINT variable to return number of bytes read.
    +
    Pointer to the UINT variable to return number of bytes read. Return value is always valid after the function call.
    diff --git a/doc/en/readdir.html b/doc/en/readdir.html index 8ccd7a3..2e8969b 100644 --- a/doc/en/readdir.html +++ b/doc/en/readdir.html @@ -51,9 +51,10 @@ FRESULT f_readdir (

    Description

    -

    The f_readdir function reads directory entries in sequence. All items in the directory can be read by calling f_readdir function repeatedly. When all directory items have been read and no item to read, the function returns a null string into f_name[] member without any error. When a null pointer is given to the FileInfo, the read index of the directory object will be rewinded.

    -

    When LFN feature is enabled, lfname and lfsize in the file information structure must be initialized with valid value prior to calling the f_readdir function. The lfname is a pointer to the string buffer to return the long file name. The lfsize is the size of the string buffer. When either the size of specified buffer or LFN working buffer is insufficient to store the LFN or LFN is not exist, a null string will be returned. When lfname is a NULL, nothing is returned.

    -

    For details on the file informations, refer to the FILINFO. This function is not supported in minimization level of >=2.

    +

    The f_readdir function reads directory entries in sequence. All items in the directory can be read by calling f_readdir function repeatedly. When all directory entries have been read and no item to read, the function returns a null string into f_name[] member without any error. When a null pointer is given to the FileInfo, the read index of the directory object will be rewinded.

    +

    When LFN feature is enabled, lfname and lfsize in the file information structure must be initialized with valid value prior to calling the f_readdir function. The lfname is a pointer to the string buffer to return the long file name. The lfsize is the size of the string buffer. If either the size of read buffer or LFN working buffer is insufficient for the LFN or the entry has no LFN, a null string will be returned to the LFN read buffer. If the LFN contains any charactrer that cannot be converted to OEM code, a null string will be returned but this is not the case on Unicode API configuration. When lfname is a NULL, nothing of the LFN is returned.

    +

    When relative path feature is enabled (_FS_RPATH == 1), "." and ".." entries are not filtered out and it will appear in the read entries.

    +

    This function is not supported in minimization level of >=2.

    @@ -85,6 +86,7 @@ FRESULT scan_files (char* path) #else fn = fno.fname; #endif + if (*fn == '.') continue; if (fno.fattrib & AM_DIR) { sprintf(&path[i], "/%s", fn); res = scan_files(path); diff --git a/doc/en/rename.html b/doc/en/rename.html index 1a0f50d..3b42175 100644 --- a/doc/en/rename.html +++ b/doc/en/rename.html @@ -15,8 +15,8 @@

    Rename file or directory.

     FRESULT f_rename (
    -  const char* OldName, /* Pointer to old file/directory name */
    -  const char* NewName  /* Pointer to new file/directory name */
    +  const XCHAR* OldName, /* Pointer to old file/directory name */
    +  const XCHAR* NewName  /* Pointer to new file/directory name */
     );
     
    diff --git a/doc/en/sdir.html b/doc/en/sdir.html index fb24961..d759eca 100644 --- a/doc/en/sdir.html +++ b/doc/en/sdir.html @@ -12,20 +12,20 @@

    DIR

    -

    The DIR structure is used for the work area to read a directory by f_oepndir, f_readdir function.

    +

    The DIR structure is used for the work area to read a directory by f_oepndir, f_readdir function. There is no member that can be changed by application.

    -typedef struct _DIR {
    -    WORD    id;        /* Owner file system mount ID */
    -    WORD    index;     /* Current index number */
    -    FATFS*  fs;        /* Pointer to the owner file system object */
    -    DWORD   sclust;    /* Table start cluster (0:Static table) */
    -    DWORD   clust;     /* Current cluster */
    -    DWORD   sect;      /* Current sector */
    -    BYTE*   dir;       /* Pointer to the current SFN entry in the win[] */
    -    BYTE*   fn;        /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
    +typedef struct _DIR_ {
    +    FATFS*  fs;         /* Pointer to the owner file system object */
    +    WORD    id;         /* Owner file system mount ID */
    +    WORD    index;      /* Current read/write index number */
    +    DWORD   sclust;     /* Table start cluster (0:Static table) */
    +    DWORD   clust;      /* Current cluster */
    +    DWORD   sect;       /* Current sector */
    +    BYTE*   dir;        /* Pointer to the current SFN entry in the win[] */
    +    BYTE*   fn;         /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
     #if _USE_LFN
    -    WCHAR*  lfn;       /* Pointer to the LFN working buffer */
    -    WORD    lfn_idx;   /* Last matched LFN index (0xFFFF:No LFN) */
    +    WCHAR*  lfn;        /* Pointer to the LFN working buffer */
    +    WORD    lfn_idx;    /* Last matched LFN index (0xFFFF:No LFN) */
     #endif
     } DIR;
     
    diff --git a/doc/en/sfatfs.html b/doc/en/sfatfs.html index f186805..42e24a2 100644 --- a/doc/en/sfatfs.html +++ b/doc/en/sfatfs.html @@ -14,35 +14,36 @@

    FATFS

    The FATFS structure holds dynamic work area of individual logical drives. It is given by application program and registerd/unregisterd to the FatFs module with f_mount function. Following members are in standard configuration. There is no member that can be changed from the application program.

    -typedef struct _FATFS {
    -    BYTE    fs_type;      /* FAT sub type */
    -    BYTE    drive;        /* Physical drive number */
    -    BYTE    csize;        /* Number of sectors per cluster */
    -    BYTE    n_fats;       /* Number of FAT copies */
    -    BYTE    wflag;        /* win[] dirty flag (1:must be written back) */
    -    BYTE    pad1;
    -    WORD    id;           /* File system mount ID */
    -    WORD    n_rootdir;    /* Number of root directory entries (0 on FAT32) */
    +typedef struct _FATFS_ {
    +    BYTE    fs_type;    /* FAT sub type */
    +    BYTE    drive;      /* Physical drive number */
    +    BYTE    csize;      /* Number of sectors per cluster */
    +    BYTE    n_fats;     /* Number of FAT copies */
    +    BYTE    wflag;      /* win[] dirty flag (1:must be written back) */
    +    WORD    id;         /* File system mount ID */
    +    WORD    n_rootdir;  /* Number of root directory entries (0 on FAT32) */
     #if _FS_REENTRANT
    -    HANDLE  h_mutex;      /* Handle to the mutex (Platform dependent) */
    +    _SYNC_t sobj;       /* Identifier of sync object */
     #endif
     #if _MAX_SS != 512
    -    WORD    s_size;       /* Sector size */
    +    WORD    s_size;     /* Sector size */
     #endif
     #if !_FS_READONLY
    -    BYTE    fsi_flag;     /* fsinfo dirty flag (1:must be written back) */
    -    BYTE    pad2;
    -    DWORD   last_clust;   /* Last allocated cluster */
    -    DWORD   free_clust;   /* Number of free clusters */
    -    DWORD   fsi_sector;   /* fsinfo sector */
    +    BYTE    fsi_flag;   /* fsinfo dirty flag (1:must be written back) */
    +    DWORD   last_clust; /* Last allocated cluster */
    +    DWORD   free_clust; /* Number of free clusters */
    +    DWORD   fsi_sector; /* fsinfo sector */
     #endif
    -    DWORD   sects_fat;    /* Sectors per fat */
    -    DWORD   max_clust;    /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
    -    DWORD   fatbase;      /* FAT start sector */
    -    DWORD   dirbase;      /* Root directory start sector (Cluster# on FAT32) */
    -    DWORD   database;     /* Data start sector */
    -    DWORD   winsect;      /* Current sector appearing in the win[] */
    -    BYTE    win[MAX_SS];  /* Disk access window for Directory/FAT */
    +#if _FS_RPATH
    +    DWORD   cdir;       /* Current directory (0:root)*/
    +#endif
    +    DWORD   sects_fat;  /* Sectors per fat */
    +    DWORD   max_clust;  /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
    +    DWORD   fatbase;    /* FAT start sector */
    +    DWORD   dirbase;    /* Root directory start sector (Cluster# on FAT32) */
    +    DWORD   database;   /* Data start sector */
    +    DWORD   winsect;    /* Current sector appearing in the win[] */
    +    BYTE    win[_MAX_SS];/* Disk access window for Directory/FAT */
     } FATFS;
     
    diff --git a/doc/en/sfile.html b/doc/en/sfile.html index 655e23f..386e615 100644 --- a/doc/en/sfile.html +++ b/doc/en/sfile.html @@ -15,22 +15,22 @@

    The FIL structure (file object) holds state of an open file. It is initialzed by f_open function and discarded by f_close function. There is no member that can be changed by the application program.

    -typedef struct _FIL {
    -    FATFS*  fs;           /* Pointer to the owner file system object */
    -    WORD    id;           /* Owner file system mount ID */
    -    BYTE    flag;         /* File status flags */
    -    BYTE    csect;        /* Sector address in the cluster */
    -    DWORD   fptr;         /* File R/W pointer */
    -    DWORD   fsize;        /* File size */
    -    DWORD   org_clust;    /* File start cluster */
    -    DWORD   curr_clust;   /* Current cluster */
    -    DWORD   dsect;        /* Current data sector */
    -#if _FS_READONLY == 0
    -    DWORD   dir_sect;     /* Sector containing the directory entry */
    -    BYTE*   dir_ptr;      /* Ponter to the directory entry in the window */
    +typedef struct _FIL_ {
    +    FATFS*  fs;         /* Pointer to the owner file system object */
    +    WORD    id;         /* Owner file system mount ID */
    +    BYTE    flag;       /* File status flags */
    +    BYTE    csect;      /* Sector address in the cluster */
    +    DWORD   fptr;       /* File R/W pointer */
    +    DWORD   fsize;      /* File size */
    +    DWORD   org_clust;  /* File start cluster */
    +    DWORD   curr_clust; /* Current cluster */
    +    DWORD   dsect;      /* Current data sector */
    +#if !_FS_READONLY
    +    DWORD   dir_sect;   /* Sector containing the directory entry */
    +    BYTE*   dir_ptr;    /* Ponter to the directory entry in the window */
     #endif
     #if !_FS_TINY
    -    BYTE    buf[SS_MAX];  /* File R/W buffer */
    +    BYTE    buf[_MAX_SS];/* File R/W buffer */
     #endif
     } FIL;
     
    diff --git a/doc/en/sfileinfo.html b/doc/en/sfileinfo.html index 104a833..6ead1e6 100644 --- a/doc/en/sfileinfo.html +++ b/doc/en/sfileinfo.html @@ -14,15 +14,15 @@

    FILINFO

    The FILINFO structure holds a file information returned by f_stat and f_readdir function.

    -typedef struct _FILINFO {
    -    DWORD fsize;     /* File size */
    -    WORD fdate;      /* Last modified date */
    -    WORD ftime;      /* Last modified time */
    -    BYTE fattrib;    /* Attribute */
    -    char fname[13];  /* Short file name (8.3 format) */
    +typedef struct _FILINFO_ {
    +    DWORD fsize;      /* File size */
    +    WORD  fdate;      /* Last modified date */
    +    WORD  ftime;      /* Last modified time */
    +    BYTE  fattrib;    /* Attribute */
    +    char  fname[13];  /* Short file name (8.3 format) */
     #if _USE_LFN
    -    char* lfname;    /* Pointer to the LFN buffer */
    -    int lfsize;      /* Size of LFN buffer [bytes] */
    +    XCHAR* lfname;    /* Pointer to the LFN buffer */
    +    int   lfsize;     /* Size of LFN buffer [characters] */
     #endif
     } FILINFO;
     
    @@ -59,9 +59,9 @@ typedef struct _FILINFO {
    fname[]
    Indicates the file/directory name in 8.3 format null-terminated string.
    lfname
    -
    Pointer to the buffer to store the long file name. This member must be initialized by application.
    +
    Pointer to the LFN buffer to store the read LFN. This member must be initialized by application prior to use this structure. Not available on non-LFN configuration.
    lfsize
    -
    Size of long file name buffer. This member must be initialized by application.
    +
    Size of the LFN buffer in unit of chars. This member must be initialized by application prior to use this structure. Not available on non-LFN configuration.

    Return

    diff --git a/doc/en/stat.html b/doc/en/stat.html index 44b39b8..49eb254 100644 --- a/doc/en/stat.html +++ b/doc/en/stat.html @@ -15,7 +15,7 @@

    The f_stat gets the file status.

     FRESULT f_stat (
    -  const char* FileName,   /* Pointer to the file or directory name */
    +  const XCHAR* FileName,  /* Pointer to the file or directory name */
       FILINFO* FileInfo       /* Pointer to the FILINFO structure */
     );
     
    diff --git a/doc/en/unlink.html b/doc/en/unlink.html index 4149cdc..955a24c 100644 --- a/doc/en/unlink.html +++ b/doc/en/unlink.html @@ -15,7 +15,7 @@

    The f_unlink removes file or directory.

     FRESULT f_unlink (
    -  const char* FileName  /* Pointer to the file or directory name */
    +  const XCHAR* FileName  /* Pointer to the file or directory name */
     );
     
    diff --git a/doc/en/utime.html b/doc/en/utime.html index 4d118ce..b940c71 100644 --- a/doc/en/utime.html +++ b/doc/en/utime.html @@ -15,7 +15,7 @@

    The f_utime function changes the timestamp of a file or directory.

     FRESULT f_utime (
    -  const char* FileName,    /* Pointer to the file or directory path */
    +  const XCHAR* FileName,   /* Pointer to the file or directory path */
       const FILINFO* TimeDate  /* Time and data to be set */
     );
     
    diff --git a/doc/en/write.html b/doc/en/write.html index 13b2bb6..a7f9d7b 100644 --- a/doc/en/write.html +++ b/doc/en/write.html @@ -33,7 +33,7 @@ FRESULT f_write (
    ByteToWrite
    Specifies number of bytes to write in range of UINT.
    ByteWritten
    -
    Pointer to the UINT variable to return number of bytes written.
    +
    Pointer to the UINT variable to return number of bytes written. Return value is always valid after the function call.
    diff --git a/doc/ja/appnote.html b/doc/ja/appnote.html index 2d46bcc..7379f8c 100644 --- a/doc/ja/appnote.html +++ b/doc/ja/appnote.html @@ -1,43 +1,43 @@ - + -FatFsモジュール アプリケーション・ノート +FatFs繝「繧ク繝・繝シ繝ォ 繧「繝励Μ繧ア繝シ繧キ繝ァ繝ウ繝サ繝弱シ繝 -

    FatFsモジュール アプリケーション・ノート

    +

    FatFs繝「繧ク繝・繝シ繝ォ 繧「繝励Μ繧ア繝シ繧キ繝ァ繝ウ繝サ繝弱シ繝


    -

    ポーティングの際に配慮すべきこと

    -

    FatFsモジュールは移植性に関して次の点を前提としています。

    +

    繝昴シ繝繧」繝ウ繧ー縺ョ髫帙↓驟肴ョ縺吶∋縺阪%縺ィ

    +

    FatFs繝「繧ク繝・繝シ繝ォ縺ッ遘サ讀肴ァ縺ォ髢「縺励※谺。縺ョ轤ケ繧貞燕謠舌→縺励※縺縺セ縺吶

    -

    メモリ使用量 (R0.07)

    +

    繝。繝「繝ェ菴ソ逕ィ驥 (R0.07c)

    - + - - - - + + + +
    AVRH8/300HPICTLCS-870/CV850ESSH2ARM7TDMIIA-32
    Compilergcc(WinAVR)CH38gcc(C30)CC870CCA850SHCgcc(WinARM)MSC
    CompilerWinAVR(gcc)CH38C30(gcc)CC870CCA850SHCWinARM(gcc)MSC
    _WORD_ACCESS10011001
    ROM (Full, R/W)1113610356108381516776828654106287232
    ROM (Min, R/W)70726696700798004634557065644647
    ROM (Full, R/O)52184626494967863528382646763267
    ROM (Min, R/O)36263418353649412558287432722397
    ROM (Full, R/W)1196210433107531515377478707105847337
    ROM (Min, R/W)74666799677299064901559965484787
    ROM (Full, R/O)54004687480467443539379946763380
    ROM (Min, R/O)38043527342150402561286732762533
    RAM (Static)D*2 + 2D*4 + 2D*2 + 2D*2 + 2D*4 + 2D*4 + 2D*4 + 2D*4 + 2
    RAM (Dynamic)
    (_FS_TINY == 0)
    D*560 +
    F*544
    D*560 +
    F*550
    D*560 +
    F*544
    D*560 +
    F*550
    D*560 +
    F*550
    D*560 +
    F*550
    D*560 +
    F*550
    RAM (Dynamic)
    (_FS_TINY == 1)
    D*560 +
    F*32
    D*560 +
    F*36
    D*560 +
    F*32
    D*560 +
    F*32
    D*560 +
    F*36
    D*560 +
    F*36
    D*560 +
    F*36
    D*560 +
    F*36
    -

    上の表にいくつかのターゲットにおけるメモリ使用量の例を示します。テスト時の構成オプションは次の通りです。数値の単位はバイトで、Dは論理ドライブ数、Fは同時オープン・ファイル数を示します。コンパイラの最適化オプションはコード・サイズとしています。

    +

    荳翫ョ陦ィ縺ォ縺縺上▽縺九ョ繧ソ繝シ繧イ繝繝医↓縺翫¢繧九Γ繝「繝ェ菴ソ逕ィ驥上ョ萓九r遉コ縺励∪縺吶ゅユ繧ケ繝域凾縺ョ讒区舌が繝励す繝ァ繝ウ縺ッ谺。縺ョ騾壹j縺ァ縺吶よ焚蛟、縺ョ蜊倅ス阪ッ繝舌う繝医〒縲D縺ッ隲也炊繝峨Λ繧、繝匁焚縲F縺ッ蜷梧凾繧ェ繝シ繝励Φ繝サ繝輔ぃ繧、繝ォ謨ー繧堤、コ縺励∪縺吶ゅさ繝ウ繝代う繝ゥ縺ョ譛驕ゥ蛹悶が繝励す繝ァ繝ウ縺ッ繧ウ繝シ繝峨サ繧オ繧、繧コ縺ィ縺励※縺縺セ縺吶

     _FS_READONLY     0 (R/W), 1 (R/O)
     _FS_MINIMIZE     0 (Full function), 3 (Minimized function)
    @@ -46,113 +46,127 @@ _USE_MKFS        0 (Disable f_mkfs function)
     _USE_FORWARD     0 (Disable f_forward function)
     _CODE_PAGE       932 (Japanese Shift-JIS)
     _USE_LFN         0 (Disable LFN)
    +_MAX_SS          512 (Single sector size)
    +_FS_RPATH        0 (Disable relative path)
     _MULTI_PARTITION 0 (Single partition per drive)
     _FS_REENTRANT    0 (Disable reentrancy)
     
    -

    モジュール・サイズの縮小

    -

    次の表は構成オプションの設定値によりどの機能が削除されるかを示します。

    +

    繝「繧ク繝・繝シ繝ォ繝サ繧オ繧、繧コ縺ョ邵ョ蟆

    +

    谺。縺ョ陦ィ縺ッ讒区舌が繝励す繝ァ繝ウ縺ョ險ュ螳壼、縺ォ繧医j縺ゥ縺ョ讖溯ス縺悟炎髯、縺輔l繧九°繧堤、コ縺励∪縺吶

    - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Function_FS_MINIMIZE_FS_READONLY_USE_STRFUNC_USE_MKFS_USE_FORWARD
    1231000
    f_mount
    f_open
    f_close
    f_read
    f_writex
    f_syncx
    f_lseekx
    f_opendirxx
    f_readdirxx
    f_statxxx
    f_getfreexxxx
    f_truncatexxxx
    f_unlinkxxxx
    f_mkdirxxxx
    f_chmodxxxx
    f_utimexxxx
    f_renamexxxx
    f_mkfsxx
    f_forwardx
    f_putcxx
    f_putsxx
    f_printfxx
    f_getsx
    Function_FS_MINIMIZE_FS_READONLY_USE_STRFUNC_FS_RPATH_USE_MKFS_USE_FORWARD
    12310000
    f_mount
    f_open
    f_close
    f_read
    f_writex
    f_syncx
    f_lseekx
    f_opendirxx
    f_readdirxx
    f_statxxx
    f_getfreexxxx
    f_truncatexxxx
    f_unlinkxxxx
    f_mkdirxxxx
    f_chmodxxxx
    f_utimexxxx
    f_renamexxxx
    f_chdirx
    f_chdrivex
    f_mkfsxx
    f_forwardx
    f_putcxx
    f_putsxx
    f_printfxx
    f_getsx
    -

    長いファイル名

    -

    FatFsモジュールはR0.07から長いファイル名(LFN)をサポートしました。ファイルに付けられた2つの異なる名前(短いファル名と長いファイル名)は、f_readdir関数を除くファイル操作関数において透過です。LFN機能を有効にするには、_USE_LFNを1または2に設定し、OEM-Unicode相互変換関数 ff_convert をプロジェクトに追加します。これらの関数は、cc*.cに含まれています。LFN機能は、加えてある程度のワーク・エリア(LFN操作バッファ)を必要とします。バッファ長は使用できるメモリに応じて_MAX_LFNオプションで構成されることができます。LFNの長さは最大255文字に達するので、LFN完全対応のためには_MAX_LFNは255に設定されるべきです。与えられたファイル名に対してバッファ長が不足した場合、ファイル関数はFR_INVALID_NAMEで失敗します。

    -

    LFN機能をリエントラント構成で使用する場合は、_USE_LFNは2に設定されなければなりません。この場合、ファイル関数はバッファをスタックに確保します。バッファ・サイズは、_MAX_LFN * 2 + 1 バイトになるので、呼び出し側スタックのサイズはそれを考慮した十分なサイズでなければなりません。

    +

    髟キ縺繝輔ぃ繧、繝ォ蜷

    +

    FatFs繝「繧ク繝・繝シ繝ォ縺ッR0.07縺九i髟キ縺繝輔ぃ繧、繝ォ蜷(LFN)繧偵し繝昴シ繝医@縺セ縺励◆縲ゅヵ繧。繧、繝ォ縺ォ莉倥¢繧峨l縺2縺、縺ョ逡ー縺ェ繧句錐蜑(遏ュ縺繝輔ぃ繝ォ蜷阪→髟キ縺繝輔ぃ繧、繝ォ蜷)縺ッ縲’_readdir髢「謨ー繧帝勁縺上ヵ繧。繧、繝ォ謫堺ス憺未謨ー縺ォ縺翫>縺ヲ騾城℃縺ァ縺吶LFN讖溯ス繧呈怏蜉ケ縺ォ縺吶k縺ォ縺ッ縲_USE_LFN繧1縺セ縺溘ッ2縺ォ險ュ螳壹@縲ゞnicode螟画鋤髢「謨ー ff_convert, ff_wtoupper 繧偵励Ο繧ク繧ァ繧ッ繝医↓霑ス蜉縺励∪縺吶ゅ%繧後i縺ョ髢「謨ー縺ッ縲cc*.c縺ォ蜷ォ縺セ繧後※縺縺セ縺吶LFN讖溯ス縺ッ縲∝刈縺医※縺ゅk遞句コヲ縺ョ繝ッ繝シ繧ッ繝サ繧ィ繝ェ繧「(LFN謫堺ス懊ヰ繝繝輔ぃ)繧貞ソ隕√→縺励∪縺吶ゅヰ繝繝輔ぃ髟キ縺ッ菴ソ逕ィ縺ァ縺阪k繝。繝「繝ェ縺ォ蠢懊§縺ヲ_MAX_LFN繧ェ繝励す繝ァ繝ウ縺ァ讒区舌&繧後k縺薙→縺後〒縺阪∪縺吶LFN縺ョ髟キ縺輔ッ譛螟ァ255譁蟄励↓驕斐☆繧九ョ縺ァ縲´FN螳悟ィ蟇セ蠢懊ョ縺溘a縺ォ縺ッ_MAX_LFN縺ッ255縺ォ險ュ螳壹&繧後k縺ケ縺阪〒縺吶ゆク弱∴繧峨l縺溘ヵ繧。繧、繝ォ蜷阪↓蟇セ縺励※繝舌ャ繝輔ぃ髟キ縺御ク崎カウ縺励◆蝣エ蜷医√ヵ繧。繧、繝ォ髢「謨ー縺ッFR_INVALID_NAME縺ァ螟ア謨励@縺セ縺吶

    +

    LFN讖溯ス繧偵Μ繧ィ繝ウ繝医Λ繝ウ繝域ァ区舌〒菴ソ逕ィ縺吶k蝣エ蜷医ッ縲_USE_LFN縺ッ2縺ォ險ュ螳壹&繧後↑縺代l縺ー縺ェ繧翫∪縺帙s縲ゅ%縺ョ蝣エ蜷医√ヵ繧。繧、繝ォ髢「謨ー縺ッ繝舌ャ繝輔ぃ繧偵せ繧ソ繝繧ッ縺ォ遒コ菫昴@縺セ縺吶ゅヰ繝繝輔ぃ繝サ繧オ繧、繧コ縺ッ縲(_MAX_LFN + 1) * 2繝舌う繝医↓縺ェ繧九ョ縺ァ縲∝他縺ウ蜃コ縺怜エ繧ケ繧ソ繝繧ッ縺ョ繧オ繧、繧コ縺ッ縺昴l繧定諷ョ縺励◆蜊∝縺ェ繧オ繧、繧コ縺ァ縺ェ縺代l縺ー縺ェ繧翫∪縺帙s縲

    - - - - - - - + + + + + + +
    LFN cfg on ARM7DMI
    コードページROMサイズ[bytes]
    SBCS+4719
    932(Shift-JIS)+63755
    936(GBK)+178943
    949(Korean)+141003
    950(Big5)+112631
    LFN cfg on ARM7
    繧ウ繝シ繝峨壹シ繧クROM繧オ繧、繧コ[bytes]
    SBCS+3721
    932(Shift-JIS)+62609
    936(GBK)+177797
    949(Korean)+139857
    950(Big5)+111497
    -

    LFNを有効にすると、選択されたコード・ページに応じてモジュール・サイズが増大されます。右の表に各コード・ページにおけるLFNを有効にしたときのモジュール・サイズの違いを示します。私たち日本人、中国人および韓国人は数万の文字を持ちます。不幸なことに、それは巨大なOEM−Unicode相互変換テーブルを要求し、モジュール・サイズは劇的に増大されます。その結果、LFNを有効にしたFatFsモジュールは、AVRを含む殆どの8ビット・マイコンにインプリメントされることができません。これは長い間私がLFNをインプリメントすることに興味を持ってこなかった理由です。

    -

    注: FATファイル・システム上のLFN機能はマイクロソフト社の特許です。商用製品でそれを有効にするときは、最終仕向地によってはライセンスが必要かも知れません。

    +

    LFN繧呈怏蜉ケ縺ォ縺吶k縺ィ縲驕ク謚槭&繧後◆繧ウ繝シ繝峨サ繝壹シ繧ク縺ォ蠢懊§縺ヲ繝「繧ク繝・繝シ繝ォ繝サ繧オ繧、繧コ縺悟「怜、ァ縺輔l縺セ縺吶ょ承縺ョ陦ィ縺ォ蜷繧ウ繝シ繝峨サ繝壹シ繧ク縺ォ縺翫¢繧記FN繧呈怏蜉ケ縺ォ縺励◆縺ィ縺阪ョ繝「繧ク繝・繝シ繝ォ繝サ繧オ繧、繧コ縺ョ驕輔>繧堤、コ縺励∪縺吶らァ√◆縺。譌・譛ャ莠コ縲∽クュ蝗ス莠コ縺翫h縺ウ髻灘嵜莠コ縺ッ謨ー荳縺ョ譁蟄励r謖√■縺セ縺吶ゆク榊ケク縺ェ縺薙→縺ォ縲√◎繧後ッ蟾ィ螟ァ縺ェOEMシ攻nicode逶ク莠貞、画鋤繝繝シ繝悶Ν繧定ヲ∵アゅ@縲√Δ繧ク繝・繝シ繝ォ繝サ繧オ繧、繧コ縺ッ蜉逧縺ォ蠅怜、ァ縺輔l縺セ縺吶ゅ◎縺ョ邨先棡縲´FN繧呈怏蜉ケ縺ォ縺励◆FatFs繝「繧ク繝・繝シ繝ォ縺ッ縲、VR繧貞性繧谿縺ゥ縺ョ8繝薙ャ繝医サ繝槭う繧ウ繝ウ縺ォ繧、繝ウ繝励Μ繝。繝ウ繝医&繧後k縺薙→縺後〒縺阪∪縺帙s縲縺薙l縺ッ髟キ縺髢鍋ァ√′LFN繧偵う繝ウ繝励Μ繝。繝ウ繝医☆繧九%縺ィ縺ォ闊亥袖繧呈戟縺」縺ヲ縺薙↑縺九▲縺溽炊逕ア縺ァ縺吶

    +

    豕ィ: FAT繝輔ぃ繧、繝ォ繝サ繧キ繧ケ繝繝荳翫ョLFN讖溯ス縺ッ繝槭う繧ッ繝ュ繧ス繝輔ヨ遉セ縺ョ迚ケ險ア縺ァ縺吶ょ膚逕ィ陬ス蜩√〒縺昴l繧呈怏蜉ケ縺ォ縺吶k縺ィ縺阪ッ縲∵怙邨ゆサ募髄蝨ー縺ォ繧医▲縺ヲ縺ッ繝ゥ繧、繧サ繝ウ繧ケ縺悟ソ隕√°繧ら衍繧後∪縺帙s縲

    -

    リエントランシー

    -

    異なるボリューム(論理ドライブ)に対するファイル操作は、リエントラント設定によらず常に同時平行に動作できます。同じボリュームに対するリエントランシーは_FS_REENTRANTオプションで有効にされることができます。この場合、OS依存の同期オブジェクト操作関数 ff_cre_syncobj, ff_del_syncobj, ff_req_grant と ff_rel_grant もまたプロジェクトに追加されなければなりません。サンプル・コードと解説はsyncobj.cにあります。

    -

    他のタスクがそのボリュームを使用中にファイル関数が呼び出されると、そのアクセスはそのタスクがファイル関数を抜けるまでブロックされます。もし、待ち時間が_TIMEOUTで指定された期間を越すと、その関数はFR_TIMEOUTでアボートします。いくつかのRTOSではタイムアウト機能はサポートされないかも知れません。

    -

    ひとつの例外がf_mountとf_mkfs関数にあります。これらの関数は同じボリュームに対してリエントラントではありません。これらの関数を使用するときは、他のスレッドは関連するファイルを閉じ、そのボリュームへのアクセスを避けなければなりません。

    -

    注: このセクションはFatFsモジュールそれ自体のリエントランシーについて説明しています。ディスクI/Oモジュールのリエントランシーに関しては何の前提もありません。

    +

    繝ェ繧ィ繝ウ繝医Λ繝ウ繧キ繝シ

    +

    逡ー縺ェ繧九懊Μ繝・繝シ繝(隲也炊繝峨Λ繧、繝)縺ォ蟇セ縺吶k繝輔ぃ繧、繝ォ謫堺ス懊ッ縲√Μ繧ィ繝ウ繝医Λ繝ウ繝郁ィュ螳壹↓繧医i縺壼クク縺ォ蜷梧凾蟷ウ陦後↓蜍穂ス懊〒縺阪∪縺吶ょ酔縺倥懊Μ繝・繝シ繝縺ォ蟇セ縺吶k繝ェ繧ィ繝ウ繝医Λ繝ウ繧キ繝シ縺ッ_FS_REENTRANT繧ェ繝励す繝ァ繝ウ縺ァ譛牙柑縺ォ縺輔l繧九%縺ィ縺後〒縺阪∪縺吶ゅ%縺ョ蝣エ蜷医^S萓晏ュ倥ョ蜷梧悄繧ェ繝悶ず繧ァ繧ッ繝域桃菴憺未謨ー ff_cre_syncobj, ff_del_syncobj, ff_req_grant 縺ィ ff_rel_grant 繧ゅ∪縺溘励Ο繧ク繧ァ繧ッ繝医↓霑ス蜉縺輔l縺ェ縺代l縺ー縺ェ繧翫∪縺帙s縲ゅし繝ウ繝励Ν繝サ繧ウ繝シ繝峨→隗」隱ャ縺ッsyncobj.c縺ォ縺ゅj縺セ縺吶

    +

    莉悶ョ繧ソ繧ケ繧ッ縺後◎縺ョ繝懊Μ繝・繝シ繝繧剃スソ逕ィ荳ュ縺ォ繝輔ぃ繧、繝ォ髢「謨ー縺悟他縺ウ蜃コ縺輔l繧九→縲√◎縺ョ繧「繧ッ繧サ繧ケ縺ッ縺昴ョ繧ソ繧ケ繧ッ縺後ヵ繧。繧、繝ォ髢「謨ー繧呈栢縺代k縺セ縺ァ繝悶Ο繝繧ッ縺輔l縺セ縺吶ゅb縺励∝セ縺。譎る俣縺_TIMEOUT縺ァ謖螳壹&繧後◆譛滄俣繧定カ翫☆縺ィ縲√◎縺ョ髢「謨ー縺ッFR_TIMEOUT縺ァ繧「繝懊シ繝医@縺セ縺吶ゅ>縺上▽縺九ョRTOS縺ァ縺ッ繧ソ繧、繝繧「繧ヲ繝域ゥ溯ス縺ッ繧オ繝昴シ繝医&繧後↑縺縺九b遏・繧後∪縺帙s縲

    +

    縺イ縺ィ縺、縺ョ萓句、悶′f_mount縺ィf_mkfs髢「謨ー縺ォ縺ゅj縺セ縺吶ゅ%繧後i縺ョ髢「謨ー縺ッ蜷後§繝懊Μ繝・繝シ繝縺ォ蟇セ縺励※繝ェ繧ィ繝ウ繝医Λ繝ウ繝医〒縺ッ縺ゅj縺セ縺帙s縲ゅ%繧後i縺ョ髢「謨ー繧剃スソ逕ィ縺吶k縺ィ縺阪ッ縲∽サ悶ョ繧ケ繝ャ繝繝峨ッ髢「騾」縺吶k繝輔ぃ繧、繝ォ繧帝哩縺倥√◎縺ョ繝懊Μ繝・繝シ繝縺ク縺ョ繧「繧ッ繧サ繧ケ繧帝∩縺代↑縺代l縺ー縺ェ繧翫∪縺帙s縲

    +

    豕ィ: 縺薙ョ繧サ繧ッ繧キ繝ァ繝ウ縺ッFatFs繝「繧ク繝・繝シ繝ォ縺昴l閾ェ菴薙ョ繝ェ繧ィ繝ウ繝医Λ繝ウ繧キ繝シ縺ォ縺、縺縺ヲ隱ャ譏弱@縺ヲ縺縺セ縺吶ゅョ繧」繧ケ繧ッI/O繝「繧ク繝・繝シ繝ォ縺ョ繝ェ繧ィ繝ウ繝医Λ繝ウ繧キ繝シ縺ォ髢「縺励※縺ッ菴輔ョ蜑肴署繧ゅ≠繧翫∪縺帙s縲

    -

    多重ファイル・アクセス

    -

    FatFsモジュールでは多重アクセス機能はサポートされません。ファイルに対する多重アクセスは、そのアクセス・モードによって制限されます。一つのファイルに対する多重オープンは、それらが全てリード・モードのとき許可されます。書き込みモードを含む多重オープン、また開かれているファイルに対するリネームや消去を行ってはなりません。さもないと、そのボリュームのFAT構造が破壊される可能性があります。

    +

    螟夐阪ヵ繧。繧、繝ォ繝サ繧「繧ッ繧サ繧ケ

    +

    FatFs繝「繧ク繝・繝シ繝ォ縺ァ縺ッ螟夐阪い繧ッ繧サ繧ケ讖溯ス縺ッ繧オ繝昴シ繝医&繧後∪縺帙s縲ゅヵ繧。繧、繝ォ縺ォ蟇セ縺吶k螟夐阪い繧ッ繧サ繧ケ縺ッ縲√◎縺ョ繧「繧ッ繧サ繧ケ繝サ繝「繝シ繝峨↓繧医▲縺ヲ蛻カ髯舌&繧後∪縺吶ゆク縺、縺ョ繝輔ぃ繧、繝ォ縺ォ蟇セ縺吶k螟夐阪が繝シ繝励Φ縺ッ縲√◎繧後i縺悟ィ縺ヲ繝ェ繝シ繝峨サ繝「繝シ繝峨ョ縺ィ縺崎ィア蜿ッ縺輔l縺セ縺吶よ嶌縺崎セシ縺ソ繝「繝シ繝峨r蜷ォ繧螟夐阪が繝シ繝励Φ縲√∪縺滄幕縺九l縺ヲ縺繧九ヵ繧。繧、繝ォ縺ォ蟇セ縺吶k繝ェ繝阪シ繝繧豸亥悉繧定。後▲縺ヲ縺ッ縺ェ繧翫∪縺帙s縲ゅ&繧ゅ↑縺縺ィ縲√◎縺ョ繝懊Μ繝・繝シ繝縺ョFAT讒矩縺檎エ螢翫&繧後k蜿ッ閭ス諤ァ縺後≠繧翫∪縺吶

    -

    効率的なファイル・アクセス

    -

    小規模な組込システムでのファイルの読み書きにおける効率の良いアクセスのため、アプリケーション・プログラマはFatFsモジュールの中でどのような処理が行われているか考慮すべきです。ディスク上のデータはf_read関数により次のシーケンスで転送されます。

    -

    図1. セクタ・ミスアラインド・リード (ショート)
    +

    蜉ケ邇逧縺ェ繝輔ぃ繧、繝ォ繝サ繧「繧ッ繧サ繧ケ

    +

    蟆剰ヲ乗ィ。縺ェ邨霎シ繧キ繧ケ繝繝縺ァ縺ョ繝輔ぃ繧、繝ォ縺ョ隱ュ縺ソ譖ク縺阪↓縺翫¢繧句柑邇縺ョ濶ッ縺繧「繧ッ繧サ繧ケ縺ョ縺溘a縲√い繝励Μ繧ア繝シ繧キ繝ァ繝ウ繝サ繝励Ο繧ー繝ゥ繝槭ッFatFs繝「繧ク繝・繝シ繝ォ縺ョ荳ュ縺ァ縺ゥ縺ョ繧医≧縺ェ蜃ヲ逅縺瑚。後o繧後※縺繧九°閠諷ョ縺吶∋縺阪〒縺吶ゅョ繧」繧ケ繧ッ荳翫ョ繝繝シ繧ソ縺ッf_read髢「謨ー縺ォ繧医j谺。縺ョ繧キ繝シ繧ア繝ウ繧ケ縺ァ霆「騾√&繧後∪縺吶

    +

    蝗ウ1. 繧サ繧ッ繧ソ繝サ繝溘せ繧「繝ゥ繧、繝ウ繝峨サ繝ェ繝シ繝 (繧キ繝ァ繝シ繝)
    fig.1

    -

    図2. セクタ・ミスアラインド・リード (ロング)
    +

    蝗ウ2. 繧サ繧ッ繧ソ繝サ繝溘せ繧「繝ゥ繧、繝ウ繝峨サ繝ェ繝シ繝 (繝ュ繝ウ繧ー)
    fig.2

    -

    図3. セクタ・アラインド・リード
    +

    蝗ウ3. 繧サ繧ッ繧ソ繝サ繧「繝ゥ繧、繝ウ繝峨サ繝ェ繝シ繝
    fig.3

    -

    ファイルI/Oバッファはセクタの一部のデータを読み書きするためのセクタ・バッファを意味します。セクタ・バッファは、それぞれのファイル・オブジェクト内のプライベート・セクタ・バッファまたはファイル・システム・オブジェクト内の共有セクタ・バッファのどちらかです。バッファ構成オプションの_FS_TINYは、データ転送にどちらを使うかを決定します。タイニー・バッファ(1)が選択されるとデータ・メモリの消費はそれぞれのファイル・オブジェクトで512バイト減少されます。この場合、FatFsモジュールはファイル・データの転送とFAT/ディレクトリ・アクセスにファイル・システム・オブジェクト内のセクタ・バッファだけを使用します。タイニー・バッファの欠点は、セクタ・バッファにキャッシュされたFATデータがファイル・データの転送により失われ、クラスタ境界の毎にリロードされなければならないことです。でも、悪くない性能と少ないメモリ消費の視点から多くのアプリケーションに適するでしょう。

    -

    図1はセクタの一部のデータがファイルI/Oバッファを経由で転送されることを示します。図2に示される長いデータの転送では、転送データの中間の1セクタまたはそれ以上のセクタにまたがる転送データがアプリケーション・バッファに直接転送されています。図3は転送データ全体がセクタ境界にアライメントされている場合を示しています。この場合、ファイルI/Oバッファは使用されません。直接転送においては最大の範囲のセクタがdisk_read関数で一度に読み込まれますが、クラスタ境界を越えるマルチ・セクタ転送はそれが隣接であっても行われません。

    -

    このように、セクタにアライメントしたファイルの読み書きへの配慮はバッファ経由のデータ転送を避け、読み書き性能は改善されるでしょう。その効果に加え、タイニー構成でキャッシュされたFATデータがファイル・データの転送によりフラッシュされず、非タイニー構成と同じ性能を小さなメモリ・フットプリントで達成できます。

    +

    繝輔ぃ繧、繝ォI/O繝舌ャ繝輔ぃ縺ッ繧サ繧ッ繧ソ縺ョ荳驛ィ縺ョ繝繝シ繧ソ繧定ェュ縺ソ譖ク縺阪☆繧九◆繧√ョ繧サ繧ッ繧ソ繝サ繝舌ャ繝輔ぃ繧呈э蜻ウ縺励∪縺吶ゅそ繧ッ繧ソ繝サ繝舌ャ繝輔ぃ縺ッ縲√◎繧後◇繧後ョ繝輔ぃ繧、繝ォ繝サ繧ェ繝悶ず繧ァ繧ッ繝亥縺ョ繝励Λ繧、繝吶シ繝医サ繧サ繧ッ繧ソ繝サ繝舌ャ繝輔ぃ縺セ縺溘ッ繝輔ぃ繧、繝ォ繝サ繧キ繧ケ繝繝繝サ繧ェ繝悶ず繧ァ繧ッ繝亥縺ョ蜈ア譛峨そ繧ッ繧ソ繝サ繝舌ャ繝輔ぃ縺ョ縺ゥ縺。繧峨°縺ァ縺吶ゅヰ繝繝輔ぃ讒区舌が繝励す繝ァ繝ウ縺ョ_FS_TINY縺ッ縲√ョ繝シ繧ソ霆「騾√↓縺ゥ縺。繧峨r菴ソ縺縺九r豎コ螳壹@縺セ縺吶ゅち繧、繝九シ繝サ繝舌ャ繝輔ぃ(1)縺碁∈謚槭&繧後k縺ィ繝繝シ繧ソ繝サ繝。繝「繝ェ縺ョ豸郁イサ縺ッ縺昴l縺槭l縺ョ繝輔ぃ繧、繝ォ繝サ繧ェ繝悶ず繧ァ繧ッ繝医〒512繝舌う繝域ク帛ー代&繧後∪縺吶ゅ%縺ョ蝣エ蜷医:atFs繝「繧ク繝・繝シ繝ォ縺ッ繝輔ぃ繧、繝ォ繝サ繝繝シ繧ソ縺ョ霆「騾√→FAT/繝繧」繝ャ繧ッ繝医Μ繝サ繧「繧ッ繧サ繧ケ縺ォ繝輔ぃ繧、繝ォ繝サ繧キ繧ケ繝繝繝サ繧ェ繝悶ず繧ァ繧ッ繝亥縺ョ繧サ繧ッ繧ソ繝サ繝舌ャ繝輔ぃ縺縺代r菴ソ逕ィ縺励∪縺吶ゅち繧、繝九シ繝サ繝舌ャ繝輔ぃ縺ョ谺轤ケ縺ッ縲√そ繧ッ繧ソ繝サ繝舌ャ繝輔ぃ縺ォ繧ュ繝」繝繧キ繝・縺輔l縺檳AT繝繝シ繧ソ縺後ヵ繧。繧、繝ォ繝サ繝繝シ繧ソ縺ョ霆「騾√↓繧医j螟ア繧上l縲√け繝ゥ繧ケ繧ソ蠅逡後ョ豈弱↓繝ェ繝ュ繝シ繝峨&繧後↑縺代l縺ー縺ェ繧峨↑縺縺薙→縺ァ縺吶ゅ〒繧ゅ∵が縺上↑縺諤ァ閭ス縺ィ蟆代↑縺繝。繝「繝ェ豸郁イサ縺ョ隕也せ縺九i螟壹¥縺ョ繧「繝励Μ繧ア繝シ繧キ繝ァ繝ウ縺ォ驕ゥ縺吶k縺ァ縺励g縺縲

    +

    蝗ウ1縺ッ繧サ繧ッ繧ソ縺ョ荳驛ィ縺ョ繝繝シ繧ソ縺後ヵ繧。繧、繝ォI/O繝舌ャ繝輔ぃ繧堤オ檎罰縺ァ霆「騾√&繧後k縺薙→繧堤、コ縺励∪縺吶ょ峙2縺ォ遉コ縺輔l繧矩聞縺繝繝シ繧ソ縺ョ霆「騾√〒縺ッ縲∬サ「騾√ョ繝シ繧ソ縺ョ荳ュ髢薙ョ1繧サ繧ッ繧ソ縺セ縺溘ッ縺昴l莉・荳翫ョ繧サ繧ッ繧ソ縺ォ縺セ縺溘′繧玖サ「騾√ョ繝シ繧ソ縺後い繝励Μ繧ア繝シ繧キ繝ァ繝ウ繝サ繝舌ャ繝輔ぃ縺ォ逶エ謗・霆「騾√&繧後※縺縺セ縺吶ょ峙3縺ッ霆「騾√ョ繝シ繧ソ蜈ィ菴薙′繧サ繧ッ繧ソ蠅逡後↓繧「繝ゥ繧、繝。繝ウ繝医&繧後※縺繧句エ蜷医r遉コ縺励※縺縺セ縺吶ゅ%縺ョ蝣エ蜷医√ヵ繧。繧、繝ォI/O繝舌ャ繝輔ぃ縺ッ菴ソ逕ィ縺輔l縺セ縺帙s縲ら峩謗・霆「騾√↓縺翫>縺ヲ縺ッ譛螟ァ縺ョ遽蝗イ縺ョ繧サ繧ッ繧ソ縺慧isk_read髢「謨ー縺ァ荳蠎ヲ縺ォ隱ュ縺ソ霎シ縺セ繧後∪縺吶′縲√け繝ゥ繧ケ繧ソ蠅逡後r雜翫∴繧九槭Ν繝√サ繧サ繧ッ繧ソ霆「騾√ッ縺昴l縺碁團謗・縺ァ縺ゅ▲縺ヲ繧り。後o繧後∪縺帙s縲

    +

    縺薙ョ繧医≧縺ォ縲√そ繧ッ繧ソ縺ォ繧「繝ゥ繧、繝。繝ウ繝医@縺溘ヵ繧。繧、繝ォ縺ョ隱ュ縺ソ譖ク縺阪∈縺ョ驟肴ョ縺ッ繝舌ャ繝輔ぃ邨檎罰縺ョ繝繝シ繧ソ霆「騾√r驕ソ縺代∬ェュ縺ソ譖ク縺肴ァ閭ス縺ッ謾ケ蝟縺輔l繧九〒縺励g縺縲ゅ◎縺ョ蜉ケ譫懊↓蜉縺医√ち繧、繝九シ讒区舌〒繧ュ繝」繝繧キ繝・縺輔l縺檳AT繝繝シ繧ソ縺後ヵ繧。繧、繝ォ繝サ繝繝シ繧ソ縺ョ霆「騾√↓繧医j繝輔Λ繝繧キ繝・縺輔l縺壹髱槭ち繧、繝九シ讒区舌→蜷後§諤ァ閭ス繧貞ー上&縺ェ繝。繝「繝ェ繝サ繝輔ャ繝医励Μ繝ウ繝医〒驕疲舌〒縺阪∪縺吶

    -

    クリチカル・セクション

    -

    ディスク上のFAT構造を操作している途中で、停電、不正なメディアの取り外し、回復不能なデータ・エラー等の障害が発生すると、処理が中途半端な状態で中断され、その結果としてFAT構造が破壊される可能性があります。次にFatFsモジュールにおけるクリチカル・セクションと、その間の障害により起きうるエラーの状態を示します。

    +

    繧ッ繝ェ繝√き繝ォ繝サ繧サ繧ッ繧キ繝ァ繝ウ

    +

    繝繧」繧ケ繧ッ荳翫ョFAT讒矩繧呈桃菴懊@縺ヲ縺繧矩比クュ縺ァ縲∝●髮サ縲∽ク肴ュ」縺ェ繝。繝繧」繧「縺ョ蜿悶j螟悶@縲∝屓蠕ゥ荳崎ス縺ェ繝繝シ繧ソ繝サ繧ィ繝ゥ繝シ遲峨ョ髫懷ョウ縺檎匱逕溘☆繧九→縲∝ヲ逅縺御クュ騾泌濠遶ッ縺ェ迥カ諷九〒荳ュ譁ュ縺輔l縲√◎縺ョ邨先棡縺ィ縺励※FAT讒矩縺檎エ螢翫&繧後k蜿ッ閭ス諤ァ縺後≠繧翫∪縺吶よャ。縺ォFatFs繝「繧ク繝・繝シ繝ォ縺ォ縺翫¢繧九け繝ェ繝√き繝ォ繝サ繧サ繧ッ繧キ繝ァ繝ウ縺ィ縲√◎縺ョ髢薙ョ髫懷ョウ縺ォ繧医j襍キ縺阪≧繧九お繝ゥ繝シ縺ョ迥カ諷九r遉コ縺励∪縺吶

    -図4. 長いクリチカル・セクション
    +蝗ウ4. 髟キ縺繧ッ繝ェ繝√き繝ォ繝サ繧サ繧ッ繧キ繝ァ繝ウ
    fig.4
    -図5. 最小化したクリチカル・セクション
    +蝗ウ5. 譛蟆丞喧縺励◆繧ッ繝ェ繝√き繝ォ繝サ繧サ繧ッ繧キ繝ァ繝ウ
    fig.5

    -

    赤で示したセクションを実行中に障害が発生した場合、クロス・リンクが発生して操作対象のファイル・ディレクトリが失われる可能性があります。黄色で示したセクションを実行中に障害が発生した場合、つぎのうちいずれかまたは複数の結果が生じる可能性があります。

    +

    襍、縺ァ遉コ縺励◆繧サ繧ッ繧キ繝ァ繝ウ繧貞ョ溯。御クュ縺ォ髫懷ョウ縺檎匱逕溘@縺溷エ蜷医√け繝ュ繧ケ繝サ繝ェ繝ウ繧ッ縺檎匱逕溘@縺ヲ謫堺ス懷ッセ雎。縺ョ繝輔ぃ繧、繝ォ繝サ繝繧」繝ャ繧ッ繝医Μ縺悟、ア繧上l繧句庄閭ス諤ァ縺後≠繧翫∪縺吶るサ濶イ縺ァ遉コ縺励◆繧サ繧ッ繧キ繝ァ繝ウ繧貞ョ溯。御クュ縺ォ髫懷ョウ縺檎匱逕溘@縺溷エ蜷医√▽縺弱ョ縺縺。縺縺壹l縺九∪縺溘ッ隍謨ー縺ョ邨先棡縺檎函縺倥k蜿ッ閭ス諤ァ縺後≠繧翫∪縺吶

    -

    いずれも書き込み中や操作対象でないファイルには影響はありません。これらのクリチカル・セクションは、ファイルを書き込みモードで開いている時間を最小限にするか、f_sync()を適宜使用することで図5のようにリスクを最小化することができます。

    +

    縺縺壹l繧よ嶌縺崎セシ縺ソ荳ュ繧謫堺ス懷ッセ雎。縺ァ縺ェ縺繝輔ぃ繧、繝ォ縺ォ縺ッ蠖ア髻ソ縺ッ縺ゅj縺セ縺帙s縲ゅ%繧後i縺ョ繧ッ繝ェ繝√き繝ォ繝サ繧サ繧ッ繧キ繝ァ繝ウ縺ッ縲√ヵ繧。繧、繝ォ繧呈嶌縺崎セシ縺ソ繝「繝シ繝峨〒髢九>縺ヲ縺繧区凾髢薙r譛蟆城剞縺ォ縺吶k縺九’_sync()繧帝←螳應スソ逕ィ縺吶k縺薙→縺ァ蝗ウ5縺ョ繧医≧縺ォ繝ェ繧ケ繧ッ繧呈怙蟆丞喧縺吶k縺薙→縺後〒縺阪∪縺吶

    -

    戻る

    +
    +

    繝輔ぃ繧、繝ォ蜷阪ョ螟ァ譁蟄怜、画鋤

    +

    CP932(Shift_JIS)縺ァ縺九▽髱朖FN讒区舌ョ縺ィ縺阪ッ縲∵僑蠑オ譁蟄(2繝舌う繝医ョ闍ア蟄励サ繧ュ繝ェ繝ォ譁蟄励サ繧ョ繝ェ繧キ繝」譁蟄)縺ォ蟇セ縺励※螟ァ譁蟄怜、画鋤繧定。後o縺壹∝ー乗枚蟄励ッ蟆乗枚蟄励〒繝繧」繝ャ繧ッ繝医Μ縺ォ險倬鹸繝サ豈碑シ縺輔l縺セ縺吶ゅ%繧後ッ譌・譛ャ隱朞SDOS縺ィ蜷後§莉墓ァ倥→縺ェ繧翫∪縺吶ゅ%縺ョ縺溘a縲∝ィ隗貞ー乗枚蟄励r蜷ォ繧繝輔ぃ繧、繝ォ繧剃ス懈舌☆繧九→縲仝indows迺ー蠅縺ァ縺昴ョ繝輔ぃ繧、繝ォ繧帝幕縺代↑縺上↑繧翫∪縺吶LFN讒区舌〒縺ッ螟ァ譁蟄怜、画鋤繧定。後>縺セ縺(Windows莉墓ァ)縲

    +
    + +
    +

    Unicode蜈・蜃コ蜉帙∈縺ョ蟇セ蠢

    +

    繝輔ぃ繧、繝ォ髢「謨ー縺ョ繝輔ぃ繧、繝ォ蜷榊・蜃コ蜉帙rUnicode縺ォ蛻繧頑崛縺医k縺薙→縺後〒縺阪∪縺吶りゥウ邏ー縺ッ縲繝輔ぃ繧、繝ォ蜷繧貞盾辣ァ縺励※縺上□縺輔>縲

    +
    + +

    謌サ繧

    diff --git a/doc/ja/chdir.html b/doc/ja/chdir.html new file mode 100644 index 0000000..5970fb9 --- /dev/null +++ b/doc/ja/chdir.html @@ -0,0 +1,85 @@ + + + + + + + +FatFs - f_chdir + + + + +
    +

    f_chdir

    +

    カレント・ディレクトリを変更します。

    +
    +FRESULT f_chdir (
    +  const XCHAR* Path /* ディレクトリ名へのポインタ */
    +);
    +
    +
    + +
    +

    引数

    +
    +
    Path
    +
    移動対象のディレクトリのパス名の入った'\0'で終わる文字列を指定します。
    +
    +
    + + +
    +

    戻り値

    +
    +
    FR_OK (0)
    +
    正常終了。
    +
    FR_NO_FILE
    +
    ファイルが見つからない。
    +
    FR_NO_PATH
    +
    パスが見つからない。
    +
    FR_INVALID_NAME
    +
    パス名が不正。
    +
    FR_INVALID_DRIVE
    +
    ドライブ番号が不正。
    +
    FR_NOT_READY
    +
    メディアがセットされていないなど、ディスク・ドライブが動作不能状態。
    +
    FR_WRITE_PROTECTED
    +
    メディアが書き込み禁止状態。
    +
    FR_DISK_ERR
    +
    ディスク・エラーによる失敗。
    +
    FR_INT_ERR
    +
    不正なFAT構造または内部エラーによる失敗。
    +
    FR_NOT_ENABLED
    +
    その論理ドライブにワーク・エリアが与えられていない。
    +
    FR_NO_FILESYSTEM
    +
    ディスク上に有効なFATパーテーションが見つからない。
    +
    +
    + + +
    +

    解説

    +

    f_chdir関数は各ボリュームのカレント・ディレクトリを変更します。カレント・ディレクトリはファイル・システム・オブジェクトの初期化が行われたとき、ルート・ディレクトリに設定されます。カレント・ディレクトリは、ファイル・システム・オブジェクトに記録されるため、そのボリュームを使用する全てのタスクに対して影響を与えます。この関数は相対パスが有効なとき(_FS_RPATH == 1)に使用可能となります。

    +
    + + +
    +

    サンプル・コード

    +
    +    // カレント・ドライブのカレント・ディレクトリを変更 (ルート下のdir1へ)
    +    f_chdir("/dir1");
    +
    +    // ドライブ2のカレント・ディレクトリを変更 (親ディレクトリへ)
    +    f_chdir("2:..");
    +
    +
    + +
    +

    参照

    +

    f_chdrive

    +
    + +

    戻る

    + + diff --git a/doc/ja/chdrive.html b/doc/ja/chdrive.html new file mode 100644 index 0000000..121ee39 --- /dev/null +++ b/doc/ja/chdrive.html @@ -0,0 +1,55 @@ + + + + + + + +FatFs - f_chdrive + + + + +
    +

    f_chdrive

    +

    カレント・ドライブを変更します。

    +
    +FRESULT f_chdrive (
    +  BYTE Drive /* 論理ドライブ番号 */
    +);
    +
    +
    + +
    +

    引数

    +
    +
    Drive
    +
    カレント・ドライブに設定する論理ドライブ番号を指定します。
    +
    +
    + + +
    +

    戻り値

    +
    +
    FR_OK (0)
    +
    正常終了。
    +
    FR_INVALID_DRIVE
    +
    ドライブ番号が不正。
    +
    +
    + + +
    +

    解説

    +

    f_chdrive関数はカレント・ドライブを変更します。システム起動時の初期値は0です。この設定はFatFsモジュールの静的変数に記録されるため、全てのタスクに対して影響を与えます。この関数は相対パスが有効なとき(_FS_RPATH == 1)に使用可能となります。

    +
    + +
    +

    参照

    +

    f_chdir

    +
    + +

    Return

    + + diff --git a/doc/ja/chmod.html b/doc/ja/chmod.html index ef0575f..6bb8388 100644 --- a/doc/ja/chmod.html +++ b/doc/ja/chmod.html @@ -15,9 +15,9 @@

    ファイルまたはディレクトリの属性を変更します。

     FRESULT f_chmod (
    -  const char* FileName, /* ファイルまたはディレクトリ名へのポインタ */
    -  BYTE Attribute,       /* 設定値 */
    -  BYTE AttributeMask    /* 変更マスク */
    +  const XCHAR* FileName, /* ファイルまたはディレクトリ名へのポインタ */
    +  BYTE Attribute,        /* 設定値 */
    +  BYTE AttributeMask     /* 変更マスク */
     );
     
    @@ -26,7 +26,7 @@ FRESULT f_chmod (

    引数

    FileName
    -
    属性変更対象のファイルまたはディレクトリのフルパス名の入った'\0'で終わる文字列を指定します。
    +
    属性変更対象のファイルまたはディレクトリのパス名の入った'\0'で終わる文字列を指定します。
    Attribute
    設定する属性。指定可能な属性は次の通りで、これらの組み合わせで指定します。指定されなかった属性は解除されます。
    @@ -54,7 +54,7 @@ FRESULT f_chmod (
    パスが見つからない。
    FR_INVALID_NAME
    パス名が不正。
    -
    FR_INVALID_NAME
    +
    FR_INVALID_DRIVE
    ドライブ番号が不正。
    FR_NOT_READY
    メディアがセットされていないなど、ディスク・ドライブが動作不能状態。
    diff --git a/doc/ja/dinit.html b/doc/ja/dinit.html index ef0ddd3..18fa43f 100644 --- a/doc/ja/dinit.html +++ b/doc/ja/dinit.html @@ -32,7 +32,7 @@ DSTATUS disk_initialize (

    戻り値

    この関数は戻り値としてディスク・ステータスを返します。ディスク・ステータスの詳細に関してはdisk_status()を参照してください。

    -

    FatFsモジュールは、自動マウント動作で必要に応じてこの関数を呼び出します。FatFsモジュール使用中は、アプリケーションからこの関数を呼び出すことは禁止です。

    +

    FatFsモジュールは、自動マウント動作で必要に応じてこの関数を呼び出します。FatFsモジュール使用中はアプリケーションからこの関数を呼び出してはなりません。さもないとFAT構造が破壊される可能性があります。

    diff --git a/doc/ja/filename.html b/doc/ja/filename.html index 5a7bd5e..b6eeed4 100644 --- a/doc/ja/filename.html +++ b/doc/ja/filename.html @@ -1,40 +1,52 @@ - + -FatFs - ファイル・ディレクトリの指定方法 +FatFs - 繝輔ぃ繧、繝ォ繝サ繝繧」繝ャ繧ッ繝医Μ縺ョ謖螳壽婿豕
    -

    ファイル・ディレクトリの指定方法

    -

    FatFsモジュールでのファイル、ディレクトリ、ドライブの指定方法はMS-DOSとほぼ同じです。ただし、一般的なOSのようなカレント・ディレクトリの概念は無いので、常にルート・ディレクトリから辿る絶対パスでの指定となります。パス名の指定方法と例は次の通りです。

    +

    繝輔ぃ繧、繝ォ繝サ繝繧」繝ャ繧ッ繝医Μ縺ョ謖螳壽婿豕

    +

    FatFs繝「繧ク繝・繝シ繝ォ縺ァ縺ョ繝輔ぃ繧、繝ォ縲√ョ繧」繝ャ繧ッ繝医Μ縲√ラ繝ゥ繧、繝悶ョ謖螳壽婿豕輔ッMS-DOS縺ィ縺サ縺シ蜷後§縺ァ縺吶ゅヱ繧ケ蜷阪ョ繝輔か繝シ繝槭ャ繝医ッ谺。縺ョ騾壹j縺ァ縺吶

    -
    - "[論理ドライブ番号:][/]ディレクトリ名/ファイル名"
    -
    - "file1.txt"           ファイル(ドライブ0)
    - "/file1.txt"          ↑と同じ
    - "dir1/dir2/file1.txt" ファイル(ドライブ0)
    - "2:dir3/file2.txt"    ファイル(ドライブ2)
    - "2:/dir5"             ディレクトリ(ドライブ2)
    - ""                    ルート・ディレクトリ(ドライブ0)
    - "/"                   ↑と同じ
    - "2:"                  ルート・ディレクトリ(ドライブ2)
    -
    + "[隲也炊繝峨Λ繧、繝也分蜿キ:][/]繝繧」繝ャ繧ッ繝医Μ蜷/繝輔ぃ繧、繝ォ蜷"
     
    -

    FatFsモジュールは長いファイル名および8.3形式ファイル名に対応しています。長いファイル名は、_USE_LFNオプションが選択されたとき使用可能になります。ディレクトリ・セパレータには / または \ を使用します。パス名先頭のセパレータは、あってもなくても同じです。論理ドライブ番号は、'0'〜'9'の一文字の数字とコロンで指定します。省略した場合は"0:"を指定したことになります。

    +

    FatFs繝「繧ク繝・繝シ繝ォ縺ッ髟キ縺繝輔ぃ繧、繝ォ蜷阪♀繧医ウ8.3蠖「蠑上ヵ繧。繧、繝ォ蜷阪↓蟇セ蠢懊@縺ヲ縺縺セ縺吶る聞縺繝輔ぃ繧、繝ォ蜷阪ッ縲_USE_LFN == 1縺ョ縺ィ縺堺スソ逕ィ蜿ッ閭ス縺ォ縺ェ繧翫∪縺吶ゅョ繧」繝ャ繧ッ繝医Μ繝サ繧サ繝代Ξ繝シ繧ソ縺ォ縺ッ / 縺セ縺溘ッ \ 繧剃スソ逕ィ縺励∪縺吶りォ也炊繝峨Λ繧、繝也分蜿キ縺ッ縲'0'ス'9'縺ョ荳譁蟄励ョ謨ー蟄励→繧ウ繝ュ繝ウ縺ァ謖螳壹@縺セ縺吶ら怐逡・縺励◆蝣エ蜷医ッ縲√ョ繝輔か繝ォ繝医サ繝峨Λ繧、繝(0縺セ縺溘ッ繧ォ繝ャ繝ウ繝医サ繝峨Λ繧、繝)縺碁∈謚槭&繧後∪縺

    +

    讓呎コ匁ァ区(_FS_RPATH == 0)縺ョ縺ィ縺阪ッ縲∝ィ縺ヲ縺ョ繧ェ繝悶ず繧ァ繧ッ繝医′繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ縺九i霎ソ繧狗オカ蟇セ繝代せ縺ァ謖螳壹&繧後∪縺吶0S謖蜷代↑繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ縺ィ縺縺讎ょソオ縺ッ辟。縺上√∪縺溘ラ繝繝亥錐("."繧"..")縺ッ菴ソ逕ィ縺ァ縺阪∪縺帙s縲ゅヱ繧ケ蜷榊磯ュ縺ョ繧サ繝代Ξ繝シ繧ソ縺ッ辟。隕悶&繧後∪縺吶ゅョ繝輔か繝ォ繝医サ繝峨Λ繧、繝也分蜿キ縺ッ蟶ク縺ォ0縺ォ縺ェ繧翫∪縺吶

    +

    逶ク蟇セ繝代せ繧呈怏蜉ケ(_FS_RPATH == 1)縺ォ縺励◆縺ィ縺阪ッ縲∝郁。後☆繧九そ繝代Ξ繝シ繧ソ縺ョ譛臥┌縺ォ繧医▲縺ヲ讀懃エ「髢句ァ九ョ繧」繝ャ繧ッ繝医Μ縺悟、峨o繧翫√そ繝代Ξ繝シ繧ソ縺後≠繧句エ蜷医ッ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ縺九i縲∫┌縺蝣エ蜷医ッf_chdir髢「謨ー縺ァ險ュ螳壹&繧後k繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ縺九i縺ォ縺ェ繧翫∪縺吶ゅ∪縺溘ヱ繧ケ蜷阪ョ謖螳壹↓繝峨ャ繝亥錐縺御スソ逕ィ縺ァ縺阪∪縺吶ゅョ繝輔か繝ォ繝医サ繝峨Λ繧、繝也分蜿キ縺ッf_chdrive髢「謨ー縺ァ險ュ螳壹&繧後◆蛟、縺ィ縺ェ繧翫∪縺吶

    +
    + + + + + + + + + + + + +
    繝代せ蜷_FS_RPATH == 0_FS_RPATH == 1
    file.txt繝峨Λ繧、繝0縺ョ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ荳九ョ繝輔ぃ繧、繝ォ繧ォ繝ャ繝ウ繝医サ繝峨Λ繧、繝悶ョ繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ荳九ョ繝輔ぃ繧、繝ォ
    /file.txt繝峨Λ繧、繝0縺ョ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ荳九ョ繝輔ぃ繧、繝ォ繧ォ繝ャ繝ウ繝医サ繝峨Λ繧、繝悶ョ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ荳九ョ繝輔ぃ繧、繝ォ
    繝峨Λ繧、繝0縺ョ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ繧ォ繝ャ繝ウ繝医サ繝峨Λ繧、繝悶ョ繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ
    2:繝峨Λ繧、繝2縺ョ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ繝峨Λ繧、繝2縺ョ繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ
    2:file1.txt繝峨Λ繧、繝2縺ョ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ荳九ョ繝輔ぃ繧、繝ォ繝峨Λ繧、繝2縺ョ繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ荳九ョ繝輔ぃ繧、繝ォ
    2:/繝峨Λ繧、繝2縺ョ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ繝峨Λ繧、繝2縺ョ繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ
    ../file.txt辟。蜉ケ隕ェ繝繧」繝ャ繧ッ繝医Μ荳九ョ繝輔ぃ繧、繝ォ
    .辟。蜉ケ縺薙ョ繝繧」繝ャ繧ッ繝医Μ
    ..辟。蜉ケ繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ縺ョ隕ェ繝繧」繝ャ繧ッ繝医Μ
    dir1/..辟。蜉ケ繧ォ繝ャ繝ウ繝医サ繝繧」繝ャ繧ッ繝医Μ
    /..辟。蜉ケ辟。蜉ケ(繝ォ繝シ繝医サ繝繧」繝ャ繧ッ繝医Μ縺ァ縺ッ繝峨ャ繝亥錐縺ッ菴ソ逕ィ荳榊庄)
    +


    -

    論理ドライブと物理ドライブの対応

    -

    標準構成では、それぞれの論理ドライブは同じ番号の物理ドライブに1:1で結びつけられていて、先頭の区画がマウントされます。構成オプションで_MULTI_PARTITIONを指定すると、論理ドライブに対して個別に物理ドライブ番号・区画を指定できるようになります。この構成では、論理ドライブと区画の対応を解決するためのテーブルを次に示すように定義する必要があります。

    +

    Unicode API

    +

    繝輔ぃ繧、繝ォ髢「謨ー縺ョ蜈・蜃コ蜉帙ョ縺縺。繝輔ぃ繧、繝ォ蜷阪d繝代せ蜷阪r謖螳壹☆繧句シ墓焚縺ョ蝙九ッ縲XCHAR縺ァ螳夂セゥ縺輔l縺ヲ縺縺セ縺吶′縲√%繧後i縺ッchar縺ァtypedef縺輔l縺ヲ縺縺セ縺吶ゅ◎縺励※縲_CODE_PAGE縺ァ謖螳壹&繧後k繝ュ繝シ繧ォ繝ォ繝サ繧ウ繝シ繝(SBCS縺セ縺溘ッDBCS)縺ョ譁蟄怜励→縺励※謇ア繧上l縺セ縺吶ゅヵ繧。繧、繝ォ蜷榊・蜃コ蜉帙rUnicode縺ィ縺吶k讒区(_USE_LFN != 0縺ァ縲√°縺、_LFN_UNICODE == 1)縺ォ縺励◆縺ィ縺阪ッ縲XCHAR縺ッ繝ッ繧、繝画枚蟄(unsigned short)縺ォ蛻繧頑崛繧上j縺セ縺吶ゅ%繧後↓繧医jLFN繝輔Ν蟇セ蠢懊→縺ェ繧翫√Ο繝シ繧ォ繝ォ繝サ繧ウ繝シ繝峨↓縺ェ縺譁蟄(笙・笘ュ笶カ縺ェ縺ゥ)繧ゆスソ逕ィ縺ァ縺阪∪縺吶

    +
    + +


    +
    +

    隲也炊繝峨Λ繧、繝悶→迚ゥ逅繝峨Λ繧、繝悶ョ蟇セ蠢

    +

    讓呎コ匁ァ区舌〒縺ッ縲√◎繧後◇繧後ョ隲也炊繝峨Λ繧、繝悶ッ蜷後§逡ェ蜿キ縺ョ迚ゥ逅繝峨Λ繧、繝悶↓1:1縺ァ邨舌ウ縺、縺代i繧後※縺縺ヲ縲∫黄逅繝峨Λ繧、繝悶ョ蜈磯ュ縺ョ蛹コ逕サ縺後槭え繝ウ繝医&繧後∪縺吶_MULTI_PARTITION == 1繧呈欠螳壹☆繧九→縲∬ォ也炊繝峨Λ繧、繝悶↓蟇セ縺励※蛟句挨縺ォ迚ゥ逅繝峨Λ繧、繝也分蜿キ繝サ蛹コ逕サ繧呈欠螳壹〒縺阪k繧医≧縺ォ縺ェ繧翫∪縺吶ゅ%縺ョ讒区舌〒縺ッ縲∬ォ也炊繝峨Λ繧、繝悶→蛹コ逕サ縺ョ蟇セ蠢懊r隗」豎コ縺吶k縺溘a縺ョ繝繝シ繝悶Ν繧呈ャ。縺ォ遉コ縺吶h縺縺ォ螳夂セゥ縺吶k蠢隕√′縺ゅj縺セ縺吶

    -例:論理ドライブ0〜2を物理ドライブ0(固定ディスク)の3つの基本区画に割り当て、
    -   論理ドライブ3を物理ドライブ1(リムーバブル・ディスク)に割り当てる場合。
    +萓:隲也炊繝峨Λ繧、繝0ス2繧堤黄逅繝峨Λ繧、繝0(蝗コ螳壹ョ繧」繧ケ繧ッ)縺ョ3縺、縺ョ蝓コ譛ャ蛹コ逕サ縺ォ蜑イ繧雁ス薙※縲
    +   隲也炊繝峨Λ繧、繝3繧堤黄逅繝峨Λ繧、繝1(繝ェ繝繝シ繝舌ヶ繝ォ繝サ繝繧」繧ケ繧ッ)縺ォ蜑イ繧雁ス薙※繧句エ蜷医
     
     const PARTITION Drives[] = {
         {0, 0},     /* Logical drive 0 ==> Physical drive 0, 1st partition */
    @@ -43,13 +55,12 @@ const PARTITION Drives[] = {
         {1, 0}      /* Logical drive 3 ==> Physical drive 1 */
     };
     
    -

    複数区画指定を使用する場合、次の点に注意しなければなりません。 +

    隍謨ー蛹コ逕サ謖螳壹r菴ソ逕ィ縺吶k蝣エ蜷医∵ャ。縺ョ轤ケ縺ォ豕ィ諢上@縺ェ縺代l縺ー縺ェ繧翫∪縺帙s縲

      -
    • 指定可能な区画は基本区画(0〜3)のみ。
    • -
    • 物理ドライブがSFD形式(区画テーブル無し)の場合、区画指定は無視される。
    • -
    • 複数の論理ドライブを持つ物理ドライブは、固定ディスクでなければならない。
    • +
    • 謖螳壼庄閭ス縺ェ蛹コ逕サ縺ッ蝓コ譛ャ蛹コ逕サ(0ス3)縺ョ縺ソ縲
    • +
    • 迚ゥ逅繝峨Λ繧、繝悶′SFD蠖「蠑(蛹コ逕サ繝繝シ繝悶Ν辟。縺)縺ョ蝣エ蜷医∝玄逕サ謖螳壹ッ辟。隕悶&繧後k縲
    • +
    • 隍謨ー縺ョ隲也炊繝峨Λ繧、繝悶r謖√▽迚ゥ逅繝峨Λ繧、繝悶ッ縲∝崋螳壹ョ繧」繧ケ繧ッ縺ァ縺ェ縺代l縺ー縺ェ繧峨↑縺縲
    -
    diff --git a/doc/ja/getfree.html b/doc/ja/getfree.html index 78108e2..03c165b 100644 --- a/doc/ja/getfree.html +++ b/doc/ja/getfree.html @@ -15,7 +15,7 @@

    論理ドライブ上の未使用クラスタ数を得ます。

     FRESULT f_getfree (
    -  const char* Path,        /* 対象ドライブのルート・ディレクトリ */
    +  const XCHAR* Path,       /* 対象ドライブのルート・ディレクトリ */
       DWORD* Clusters,         /* 空きクラスタ数を格納する変数へのポインタ */
       FATFS** FileSystemObject /* ファイル・システム・オブジェクトを指すポインタへのポインタ */
     );
    @@ -67,18 +67,21 @@ FRESULT f_getfree (
     

    使用例

         FATFS *fs;
    -    DWORD clust;
    +    DWORD fre_clust, fre_sect, tot_sect;
     
     
    -    // Get free clusters
    -    res = f_getfree("", &clust, &fs);
    +    // Get drive information and free clusters
    +    res = f_getfree("/", &fre_clust, &fs);
         if (res) die(res);
     
    -    // Get free space
    -    printf("%lu KB total disk space.\n"
    -           "%lu KB available on the disk.\n",
    -           (DWORD)(fs->max_clust - 2) * fs->csize / 2,
    -           clust * fs->csize / 2);
    +    // Get total sectors and free sectors
    +    tot_sect = (fs->max_clust - 2) * fs->csize;
    +    fre_sect = fre_clust * fs->csize;
    +
    +    // Print free space in unit of KB (assuming 512B/sector)
    +    printf("%lu KB total drive space.\n"
    +           "%lu KB available.\n",
    +           fre_sect / 2, tot_sect / 2);
     
    diff --git a/doc/ja/lseek.html b/doc/ja/lseek.html index 2717c97..8d336ca 100644 --- a/doc/ja/lseek.html +++ b/doc/ja/lseek.html @@ -66,28 +66,28 @@ FRESULT f_lseek ( // ファイル・オフセット5000へ移動 res = f_lseek(&file, 5000); + // ファイル追記の準備 (ファイル終端へ移動) + res = f_lseek(&file, file.fsize); + // 3000バイト進める res = f_lseek(&file, file.fptr + 3000); // 2000バイト戻す (オーバーフローに注意) res = f_lseek(&file, file.fptr - 2000); - - // ファイル追記の準備 (ファイル終端へ移動) - res = f_lseek(&file, file.fsize);
    -    // クラスタ先行割り当て (データ・オーバーランの防止)
    +    // クラスタ先行割り当て (ストリーミング・ライト時のバッファ・オーバーラン防止)
     
         res = f_open(&file, "record.wav", FA_CREATE_NEW | FA_WRITE); // ファイル作成
     
    -    res = f_lseek(&file, MAX_SIZE);    // 十分なクラスタの先行割り当て
    +    res = f_lseek(&file, MAX_SIZE);        // 十分なクラスタの先行割り当て
         if (res || file.fptr != PRE_SIZE) .... // 正しくファイルが拡張されたかチェック
     
    -    res = f_lseek(&file, DATA_START);  // データ・ストリームの記録(アロケーションディレイ無し)
    +    res = f_lseek(&file, DATA_START);      // データ・ストリームの記録(アロケーションディレイ無し)
         ...
     
    -    res = f_truncate(&file);          // 不要領域の切り捨て
    -    res = f_lseek(&file, 0);          // ヘッダの記録
    +    res = f_truncate(&file);              // 不要領域の切り捨て
    +    res = f_lseek(&file, 0);              // ヘッダの記録
         ...
     
         res = f_close(&file);
    diff --git a/doc/ja/mkdir.html b/doc/ja/mkdir.html
    index f82fa5c..57ae209 100644
    --- a/doc/ja/mkdir.html
    +++ b/doc/ja/mkdir.html
    @@ -15,7 +15,7 @@
     

    ディレクトリを作成します。

     FRESULT f_mkdir (
    -  const char* DirName /* 作成するディレクトリ名へのポインタ */
    +  const XCHAR* DirName /* 作成するディレクトリ名へのポインタ */
     );
     
    @@ -24,7 +24,7 @@ FRESULT f_mkdir (

    引数

    DirName
    -
    作成するディレクトリのフルパス名が入った'\0'で終わる文字列へのポインタを指定します。
    +
    作成するディレクトリのパス名が入った'\0'で終わる文字列へのポインタを指定します。
    diff --git a/doc/ja/mountdrv.html b/doc/ja/mountdrv.html deleted file mode 100644 index 96b7d55..0000000 --- a/doc/ja/mountdrv.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - -FatFs - f_mountdrv - - - - -
    -

    f_mountdrv

    -

    ファイルシステムを明示的に初期化します。

    -
    -FRESULT f_mountdrv (void);
    -
    -
    - -
    -

    戻り値

    -
    -
    FR_OK (0)
    -
    正常終了。
    -
    FR_NOT_READY
    -
    メディアがセットされていないなど、ディスクドライブが動作不能状態。
    -
    FR_RW_ERROR
    -
    ディスクアクセスでエラーが発生した。
    -
    FR_NOT_ENABLED
    -
    FatFsモジュールが停止状態。
    -
    FR_NO_FILESYSTEM
    -
    ディスク上に有効なFATファイルシステムが見つからない。
    -
    -
    - - -
    -

    解説

    -

    ファイルシステムを強制的に初期化(マウント)します。FatFsモジュールではマウント動作はファイル関数呼び出し時に必要に応じて内部で行われるので、通常はこの関数を使用すべきではありません。自動マウント動作中に回復不能エラー(たとえばFR_INCORRECT_DISK_CHANGE)が発生した場合、全てのファイル関数が使えなくなるので、そのときはこの関数で再マウントして回復することができます。

    -

    f_mountdrv関数内では次の処理が行われます。

    -
    -
      -
    • 下位レイヤ(ディスクI/Oモジュール)の初期化。
    • -
    • FATブートレコードの検索。先頭セクタ(SFD)→第一基本区画(FDISK)の順に検索します。
    • -
    • ファイルシステムオブジェクト構造体の初期化。
    • -
    -
    - - -
    -

    参照

    -

    FATFS

    -
    - -

    戻る

    - - diff --git a/doc/ja/open.html b/doc/ja/open.html index 000bf98..5829d0f 100644 --- a/doc/ja/open.html +++ b/doc/ja/open.html @@ -15,9 +15,9 @@

    ファイルをオープンまたは作成します。

     FRESULT f_open (
    -  FIL* FileObject,      /* 空のファイル・オブジェクト構造体へのポインタ */
    -  const char* FileName, /* ファイルのフルパス名へのポインタ */
    -  BYTE ModeFlags        /* モードフラグ */
    +  FIL* FileObject,       /* 空のファイル・オブジェクト構造体へのポインタ */
    +  const XCHAR* FileName, /* ファイルのフルパス名へのポインタ */
    +  BYTE ModeFlags         /* モードフラグ */
     );
     
    @@ -89,23 +89,24 @@ FRESULT f_open (

    使用例(ファイル・コピー)

    -void main ()
    +void main (void)
     {
    -    FATFS fs;            // 論理ドライブのワーク・エリア(ファイル・システム・オブジェクト)
    +    FATFS fs[2];         // 論理ドライブのワーク・エリア(ファイル・システム・オブジェクト)
         FIL fsrc, fdst;      // ファイル・オブジェクト
         BYTE buffer[4096];   // file copy buffer
         FRESULT res;         // FatFs function common result code
         UINT br, bw;         // File R/W count
     
    -    // ドライブ0のワーク・エリアを与える
    -    f_mount(0, &fs);
    +    // ドライブ0,1にワーク・エリアを与える
    +    f_mount(0, &fs[0]);
    +    f_mount(1, &fs[1]);
     
    -    // ソース・ファイルを開く
    -    res = f_open(&fsrc, "srcfile.dat", FA_OPEN_EXISTING | FA_READ);
    +    // ドライブ1のソース・ファイルを開く
    +    res = f_open(&fsrc, "1:srcfile.dat", FA_OPEN_EXISTING | FA_READ);
         if (res) die(res);
     
    -    // デスティネーション・ファイルを作成する
    -    res = f_open(&fdst, "dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE);
    +    // ドライブ0にデスティネーション・ファイルを作成する
    +    res = f_open(&fdst, "0:dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE);
         if (res) die(res);
     
         // ソースからデスティネーションにコピーする
    @@ -122,6 +123,7 @@ void main ()
     
         // ワーク・エリアを開放する
         f_mount(0, NULL);
    +    f_mount(1, NULL);
     }
     
    diff --git a/doc/ja/opendir.html b/doc/ja/opendir.html index 41d60d4..809b9e4 100644 --- a/doc/ja/opendir.html +++ b/doc/ja/opendir.html @@ -15,8 +15,8 @@

    ディレクトリをオープンします。

     FRESULT f_opendir (
    -  DIR* DirObject,      /* ディレクトリ・ブジェクト構造体へのポインタ */
    -  const char* DirName  /* ディレクトリ名へのポインタ */
    +  DIR* DirObject,       /* ディレクトリ・ブジェクト構造体へのポインタ */
    +  const XCHAR* DirName  /* ディレクトリ名へのポインタ */
     );
     
    @@ -27,7 +27,7 @@ FRESULT f_opendir (
    DirObject
    初期化するディレクトリ・オブジェクト構造体へのポインタを指定します。
    DirName
    -
    オープンするディレクトリのフルパス名が入った'\0'で終わる文字列へのポインタを指定します。
    +
    オープンするディレクトリへのパス名が入った'\0'で終わる文字列へのポインタを指定します。
    diff --git a/doc/ja/read.html b/doc/ja/read.html index 1e352fe..c37fddb 100644 --- a/doc/ja/read.html +++ b/doc/ja/read.html @@ -33,7 +33,7 @@ FRESULT f_read (
    ByteToRead
    読み出すバイト数(0〜UINTの最大値)を指定します。
    ByteRead
    -
    実際に読み出されたバイト数を格納する変数を指すポインタを指定します。
    +
    実際に読み出されたバイト数を格納する変数を指すポインタを指定します。戻り値は常に有効です。
    diff --git a/doc/ja/readdir.html b/doc/ja/readdir.html index 621ae35..a76e24a 100644 --- a/doc/ja/readdir.html +++ b/doc/ja/readdir.html @@ -51,8 +51,8 @@ FRESULT f_readdir (

    解説

    -

    ディレクトリ項目を順次読み出します。この関数を繰り返し実行することによりディレクトリの全ての項目を読み出すことができます。全ての項目を読み出し、読み出す項目がもう無いときは、f_name[]メンバにヌル文字列が返されます。得られるファイル情報の詳細については FILINFO構造体を参照してください。FileInfoにヌル・ポインタを指定すると、そのディレクトリのリード・インデックスを巻き戻します。

    -

    LFN機能が有効な時は、f_readdir関数の呼び出しに先立ってFILINFO構造体のlfnamelfsizeが有効な値で初期化されていなければなりません。lfnameはLFNを格納するバッファで、lfsizeはそのバッファ・サイズです。LFN格納バッファまたはLFN操作バッファどちらかのサイズがそのLFNのサイズに対して不十分だった場合、またはLFNが存在しない場合はLFN格納バッファにヌル文字列が返されます。lfnameにヌル・ポインタを指定した場合は、LFNに関して何も返されません。

    +

    ディレクトリ項目を順次読み出します。この関数を繰り返し実行することによりディレクトリの全ての項目を読み出すことができます。全ての項目を読み出し、読み出す項目がもう無いときは、f_name[]メンバにヌル文字列が返されます。ボリューム名は読み出すときに棄てられ、現れることはありません。"."、".."は、相対パスが有効なとき(_FS_RPATH == 1)のみ現れます。得られるファイル情報の詳細については FILINFO構造体を参照してください。FileInfoにヌル・ポインタを指定すると、そのディレクトリのリード・インデックスを巻き戻します。

    +

    LFN機能が有効な時は、f_readdir関数の呼び出しに先立ってFILINFO構造体のlfnamelfsizeが有効な値で初期化されていなければなりません。lfnameはLFNを格納するバッファで、lfsizeはそのバッファ・サイズです。LFN格納バッファまたはLFN操作バッファどちらかのサイズがそのLFNのサイズに対して不十分だった場合またはLFNが存在しない場合は、LFN格納バッファにヌル文字列が返されます。LFNにローカル・コードに存在しない文字が含まれている場合も同様ですが、Unicode APIが指定されている場合は文字コードの制約はありません。lfnameにヌル・ポインタを指定した場合は、LFNに関して何も返されません。

    _FS_MINIMIZE >= 2ではこの関数はサポートされません。

    @@ -85,6 +85,7 @@ FRESULT scan_files (char* path) #else fn = fno.fname; #endif + if (*fn == '.') continue; if (fno.fattrib & AM_DIR) { sprintf(&path[i], "/%s", fn); res = scan_files(path); diff --git a/doc/ja/rename.html b/doc/ja/rename.html index 3f4a7d3..587c058 100644 --- a/doc/ja/rename.html +++ b/doc/ja/rename.html @@ -15,8 +15,8 @@

    ファイルまたはディレクトリの名前の変更または移動。

     FRESULT f_rename (
    -  const char* OldName, /* 古いファイルまたはディレクトリ名 */
    -  const char* NewName  /* 新しいファイルまたはディレクトリ名 */
    +  const XCHAR* OldName, /* 古いファイルまたはディレクトリ名 */
    +  const XCHAR* NewName  /* 新しいファイルまたはディレクトリ名 */
     );
     
    @@ -25,7 +25,7 @@ FRESULT f_rename (

    引数

    OldName
    -
    変更対象のオブジェクト(ファイルまたはディレクトリ)のフルパス名の入った'\0'で終わる文字列へのポインタを指定します。
    +
    変更対象のオブジェクト(ファイルまたはディレクトリ)へのパス名の入った'\0'で終わる文字列へのポインタを指定します。
    NewName
    新しいファイルまたはディレクトリのフルパス名の入った'\0'で終わる文字列へのポインタを指定します。既に存在するものと同じ名前は使えません。また、ドライブ番号は指定できず、OldNameで指定されたドライブ上のオブジェクトとして扱われます。
    diff --git a/doc/ja/sdir.html b/doc/ja/sdir.html index e6812ce..ea355ea 100644 --- a/doc/ja/sdir.html +++ b/doc/ja/sdir.html @@ -12,12 +12,12 @@

    DIR

    -

    DIR構造体は、f_opendir(), f_readdir()のワーク・エリアとして使用されます。

    +

    DIR構造体は、f_opendir(), f_readdir()のワーク・エリアとして使用されます。アプリケーションから変更可能なメンバはありません。

    -typedef struct _DIR {
    +typedef struct _DIR_ {
    +    FATFS*  fs;        /* Pointer to the owner file system object */
         WORD    id;        /* Owner file system mount ID */
         WORD    index;     /* Current index number */
    -    FATFS*  fs;        /* Pointer to the owner file system object */
         DWORD   sclust;    /* Table start cluster (0:Static table) */
         DWORD   clust;     /* Current cluster */
         DWORD   sect;      /* Current sector */
    diff --git a/doc/ja/sfatfs.html b/doc/ja/sfatfs.html
    index 9b6fbce..2cedc67 100644
    --- a/doc/ja/sfatfs.html
    +++ b/doc/ja/sfatfs.html
    @@ -15,13 +15,12 @@
     

    FATFS構造体は、個々の論理ドライブのダイナミック・ワーク・エリアを保持し、f_mount()でFatFsモジュールに登録されます。標準状態では次のようなメンバになっています。アプリケーションから書き換え可能なメンバはありません。

    -typedef struct _FATFS {
    +typedef struct _FATFS_ {
         BYTE    fs_type;      /* FAT sub type */
         BYTE    drive;        /* Physical drive number */
         BYTE    csize;        /* Number of sectors per cluster */
         BYTE    n_fats;       /* Number of FAT copies */
         BYTE    wflag;        /* win[] dirty flag (1:must be written back) */
    -    BYTE    pad1;
         WORD    id;           /* File system mount ID */
         WORD    n_rootdir;    /* Number of root directory entries (0 on FAT32) */
     #if _FS_REENTRANT
    @@ -32,7 +31,6 @@ typedef struct _FATFS {
     #endif
     #if !_FS_READONLY
         BYTE    fsi_flag;     /* fsinfo dirty flag (1:must be written back) */
    -    BYTE    pad2;
         DWORD   last_clust;   /* Last allocated cluster */
         DWORD   free_clust;   /* Number of free clusters */
         DWORD   fsi_sector;   /* fsinfo sector */
    diff --git a/doc/ja/sfile.html b/doc/ja/sfile.html
    index 5e76f26..fd8849b 100644
    --- a/doc/ja/sfile.html
    +++ b/doc/ja/sfile.html
    @@ -15,7 +15,7 @@
     

    FIL構造体は、f_open()で作成され、そのファイルの状態を保持します。アプリケーションから書き換え可能なメンバはありません。

    -typedef struct _FIL {
    +typedef struct _FIL_ {
         FATFS*  fs;           /* Pointer to the owner file system object */
         WORD    id;           /* Owner file system mount ID */
         BYTE    flag;         /* File status flags */
    diff --git a/doc/ja/sfileinfo.html b/doc/ja/sfileinfo.html
    index ee739ec..e37e39c 100644
    --- a/doc/ja/sfileinfo.html
    +++ b/doc/ja/sfileinfo.html
    @@ -14,15 +14,15 @@
     

    FILINFO

    FILINFO構造体は、f_stat(), f_readdir()で返されるファイル情報を保持します。

    -typedef struct _FILINFO {
    +typedef struct _FILINFO_ {
         DWORD fsize;     /* File size */
         WORD fdate;      /* Last modified date */
         WORD ftime;      /* Last modified time */
         BYTE fattrib;    /* Attribute */
         char fname[13];  /* Short file name (8.3 format) */
     #if _USE_LFN
    -    char* lfname;    /* Pointer to the LFN buffer */
    -    int lfsize;      /* Size of LFN buffer [bytes] */
    +    XCHAR* lfname;   /* Pointer to the LFN buffer */
    +    int lfsize;      /* Size of LFN buffer [characters] */
     #endif
     } FILINFO;
     
    @@ -58,6 +58,10 @@ typedef struct _FILINFO {
    属性フラグが格納されます。フラグはAM_DIR, AM_RDO, AM_HID, AM_SYS, AM_ARCの組み合わせとなります。
    fname[]
    8.3形式の名前が'\0'で終わる文字列として格納されます。
    +
    lfname
    +
    返される長いファイル名を格納するバッファへのポインタ。この構造体を使用する前にアプリケーションにより初期化されなければなりません。非LFN構成のときは存在しません。
    +
    lfsize
    +
    長いファイル名を格納するバッファのサイズ(文字数)。この構造体を使用する前にアプリケーションにより初期化されなければなりません。非LFN構成のときは存在しません。

    戻る

    diff --git a/doc/ja/unlink.html b/doc/ja/unlink.html index e556ba2..1e36b45 100644 --- a/doc/ja/unlink.html +++ b/doc/ja/unlink.html @@ -15,7 +15,7 @@

    ファイルまたはディレクトリを削除します。

     FRESULT f_unlink (
    -  const char* FileName  /* ファイルまたはディレクトリ名へのポインタ */
    +  const XCHAR* FileName  /* ファイルまたはディレクトリ名へのポインタ */
     );
     
    diff --git a/doc/ja/utime.html b/doc/ja/utime.html index feade7e..c47c50f 100644 --- a/doc/ja/utime.html +++ b/doc/ja/utime.html @@ -15,7 +15,7 @@

    ファイルまたはディレクトリのタイムスタンプを変更します。

     FRESULT f_utime (
    -  const char* FileName,    /* ファイルまたはディレクトリ名へのポインタ */
    +  const XCHAR* FileName,   /* ファイルまたはディレクトリ名へのポインタ */
       const FILINFO* TimeDate  /* 設定する日付 */
     );
     
    @@ -25,7 +25,7 @@ FRESULT f_utime (

    引数

    FileName
    -
    変更対象のファイルまたはディレクトリのフルパス名の入った'\0'で終わる文字列を指定します。
    +
    変更対象のファイルまたはディレクトリへのパス名の入った'\0'で終わる文字列を指定します。
    TimeDate
    設定する日付と時間をfdateとftimeメンバに設定されたFILINFO構造体へのポインタ。他のメンバはDon't careです。
    diff --git a/doc/ja/write.html b/doc/ja/write.html index 68c261a..696375d 100644 --- a/doc/ja/write.html +++ b/doc/ja/write.html @@ -33,7 +33,7 @@ FRESULT f_write (
    ByteToWrite
    書き込むバイト数(0〜UINTの最大値)を指定します。
    ByteWritten
    -
    書き込まれたバイト数を格納する変数を指すポインタを指定します。
    +
    書き込まれたバイト数を格納する変数を指すポインタを指定します。戻り値は常に有効です。
    diff --git a/doc/patches.html b/doc/patches.html new file mode 100644 index 0000000..9f49e0f --- /dev/null +++ b/doc/patches.html @@ -0,0 +1,18 @@ + + + + + + + +Patches for FatFs R0.07b + + +

    Patches for FatFs R0.07b

    +
    +Jun 21, 2009
    +------------------------------------------------------------------------------
    +Currently no known problem.
    +
    + + diff --git a/doc/updates.txt b/doc/updates.txt index f92445a..42e6ae3 100644 --- a/doc/updates.txt +++ b/doc/updates.txt @@ -1,3 +1,11 @@ +R0.07b, Jun 21, 2009 + Fixed f_unlink() may return FR_OK on error. + Fixed wrong cache control in f_lseek(). + Added relative path feature. + Added f_chdir(). + Added f_chdrive(). + Added proper case conversion to extended char. + R0.07a, Apr 14, 2009 Separated out OS dependent code on re-entrant configuration. Added multiple sector size support. diff --git a/src/00readme.txt b/src/00readme.txt index 0e06c20..741b979 100644 --- a/src/00readme.txt +++ b/src/00readme.txt @@ -1,4 +1,4 @@ -FatFs/Tiny-FatFs Module Source Files R0.07a (C)ChaN, 2009 +FatFs Module Source Files R0.07c (C)ChaN, 2009 FILES @@ -27,7 +27,7 @@ AGREEMENTS * The FatFs module is a free software and there is NO WARRANTY. * No restriction on use. You can use, modify and redistribute it for - personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY. + personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. * Redistributions of source code must retain the above copyright notice. @@ -94,3 +94,11 @@ REVISION HISTORY Apr 14, 2009, R0.07a Separated out OS dependent code on reentrant cfg. Added multiple sector size support. + + Jun 21, 2009, R0.07c Fixed f_unlink() may return FR_OK on error. + Fixed wrong cache control in f_lseek(). + Added relative path feature. + Added f_chdir(). + Added f_chdrive(). + Added proper case conversion to extended char. + diff --git a/src/ff.c b/src/ff.c index 0079c3c..0d2606e 100644 --- a/src/ff.c +++ b/src/ff.c @@ -1,17 +1,18 @@ /*----------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.07a (C)ChaN, 2009 +/ FatFs - FAT file system module R0.07c (C)ChaN, 2009 /-----------------------------------------------------------------------------/ / FatFs module is an open source software to implement FAT file system to / small embedded systems. This is a free software and is opened for education, -/ research and commercial developments under license policy of following trems. +/ research and commercial use under license policy of following trems. / / Copyright (C) 2009, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY. +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. / * Redistributions of source code must retain the above copyright notice. -//-----------------------------------------------------------------------------/ +/ +/-----------------------------------------------------------------------------/ / Feb 26,'06 R0.00 Prototype. / / Apr 29,'06 R0.01 First stable version. @@ -62,12 +63,16 @@ / Renamed string functions to avoid name collision. / Apr 14,'09 R0.07a Separated out OS dependent code on reentrant cfg. / Added multiple sector size support. +/ Jun 21,'09 R0.07c Fixed f_unlink() may return FR_OK on error. +/ Fixed wrong cache control in f_lseek(). +/ Added relative path feature. +/ Added f_chdir() and f_chdrive(). +/ Added proper case conversion to extended char. /---------------------------------------------------------------------------*/ #include "ff.h" /* FatFs configurations and declarations */ #include "diskio.h" /* Declarations of low level disk I/O functions */ - /*-------------------------------------------------------------------------- Module Private Definitions @@ -93,6 +98,16 @@ #define NULL 0 #endif +/* Name status flags */ +#define NS_LOSS 0x01 /* Lossy conversion */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ + + + /*-------------------------------------------------------------------------- @@ -102,9 +117,15 @@ static FATFS *FatFs[_DRIVES]; /* Pointer to the file system objects (logical drives) */ + static WORD Fsid; /* File system mount ID */ +#if _FS_RPATH +static +BYTE Drive; /* Current drive */ +#endif + #if _USE_LFN == 1 /* LFN with static LFN working buffer */ static @@ -222,7 +243,7 @@ FRESULT move_window ( fs->wflag = 0; if (wsect < (fs->fatbase + fs->sects_fat)) { /* In FAT area */ BYTE nf; - for (nf = fs->n_fats; nf >= 2; nf--) { /* Refrect the change to FAT copy */ + for (nf = fs->n_fats; nf > 1; nf--) { /* Refrect the change to all FAT copies */ wsect += fs->sects_fat; disk_write(fs->drive, fs->win, wsect, 1); } @@ -281,26 +302,26 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ /*-----------------------------------------------------------------------*/ -/* Get a cluster status */ +/* FAT access - Read value of a FAT entry */ /*-----------------------------------------------------------------------*/ static -DWORD get_cluster ( /* 0xFFFFFFFF:Disk error, 1:Interal error, Else:Cluster status */ - FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to get the link information */ +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Interal error, Else:Cluster status */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to get the link information */ ) { - WORD wc, bc; + UINT wc, bc; DWORD fsect; - if (clst < 2 || clst >= fs->max_clust) /* Check cluster address range */ + if (clst < 2 || clst >= fs->max_clust) /* Range check */ return 1; fsect = fs->fatbase; switch (fs->fs_type) { case FS_FAT12 : - bc = (WORD)clst * 3 / 2; + bc = clst; bc += bc / 2; if (move_window(fs, fsect + (bc / SS(fs)))) break; wc = fs->win[bc & (SS(fs) - 1)]; bc++; if (move_window(fs, fsect + (bc / SS(fs)))) break; @@ -323,30 +344,30 @@ DWORD get_cluster ( /* 0xFFFFFFFF:Disk error, 1:Interal error, Else:Cluster stat /*-----------------------------------------------------------------------*/ -/* Change a cluster status */ +/* FAT access - Change value of a FAT entry */ /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static -FRESULT put_cluster ( - FATFS *fs, /* File system object */ - DWORD clst, /* Cluster# to be changed (must be 2 to fs->max_clust-1) */ - DWORD val /* New value to mark the cluster */ +FRESULT put_fat ( + FATFS *fs, /* File system object */ + DWORD clst, /* Cluster# to be changed in range of 2 to fs->max_clust - 1 */ + DWORD val /* New value to mark the cluster */ ) { - WORD bc; + UINT bc; BYTE *p; DWORD fsect; FRESULT res; - if (clst < 2 || clst >= fs->max_clust) { /* Check cluster address range */ + if (clst < 2 || clst >= fs->max_clust) { /* Range check */ res = FR_INT_ERR; } else { fsect = fs->fatbase; switch (fs->fs_type) { case FS_FAT12 : - bc = (WORD)clst * 3 / 2; + bc = clst; bc += bc / 2; res = move_window(fs, fsect + (bc / SS(fs))); if (res != FR_OK) break; p = &fs->win[bc & (SS(fs) - 1)]; @@ -385,30 +406,30 @@ FRESULT put_cluster ( /*-----------------------------------------------------------------------*/ -/* Remove a cluster chain */ +/* FAT handling - Remove a cluster chain */ /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static FRESULT remove_chain ( FATFS *fs, /* File system object */ - DWORD clst /* Cluster# to remove chain from */ + DWORD clst /* Cluster# to remove a chain from */ ) { FRESULT res; DWORD nxt; - if (clst < 2 || clst >= fs->max_clust) { /* Check cluster address range */ + if (clst < 2 || clst >= fs->max_clust) { /* Check the range of cluster# */ res = FR_INT_ERR; } else { res = FR_OK; while (clst < fs->max_clust) { /* Not a last link? */ - nxt = get_cluster(fs, clst); /* Get cluster status */ + nxt = get_fat(fs, clst); /* Get cluster status */ if (nxt == 0) break; /* Empty cluster? */ if (nxt == 1) { res = FR_INT_ERR; break; } /* Internal error? */ if (nxt == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } /* Disk error? */ - res = put_cluster(fs, clst, 0); /* Mark the cluster "empty" */ + res = put_fat(fs, clst, 0); /* Mark the cluster "empty" */ if (res != FR_OK) break; if (fs->free_clust != 0xFFFFFFFF) { /* Update FSInfo */ fs->free_clust++; @@ -426,7 +447,7 @@ FRESULT remove_chain ( /*-----------------------------------------------------------------------*/ -/* Stretch or create a cluster chain */ +/* FAT handling - Stretch or Create a cluster chain */ /*-----------------------------------------------------------------------*/ #if !_FS_READONLY static @@ -444,7 +465,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err if (scl == 0 || scl >= mcl) scl = 1; } else { /* Stretch existing chain */ - cs = get_cluster(fs, clst); /* Check the cluster status */ + cs = get_fat(fs, clst); /* Check the cluster status */ if (cs < 2) return 1; /* It is an invalid cluster */ if (cs < mcl) return cs; /* It is already followed by next cluster */ scl = clst; @@ -457,17 +478,17 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err ncl = 2; if (ncl > scl) return 0; /* No free custer */ } - cs = get_cluster(fs, ncl); /* Get the cluster status */ + cs = get_fat(fs, ncl); /* Get the cluster status */ if (cs == 0) break; /* Found a free cluster */ if (cs == 0xFFFFFFFF || cs == 1)/* An error occured */ return cs; if (ncl == scl) return 0; /* No free custer */ } - if (put_cluster(fs, ncl, 0x0FFFFFFF)) /* Mark the new cluster "in use" */ + if (put_fat(fs, ncl, 0x0FFFFFFF)) /* Mark the new cluster "in use" */ return 0xFFFFFFFF; - if (clst != 0) { /* Link it to previous one if needed */ - if (put_cluster(fs, clst, ncl)) + if (clst != 0) { /* Link it to the previous one if needed */ + if (put_fat(fs, clst, ncl)) return 0xFFFFFFFF; } @@ -489,7 +510,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err /*-----------------------------------------------------------------------*/ static -DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */ +DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ FATFS *fs, /* File system object */ DWORD clst /* Cluster# to be converted */ ) @@ -503,7 +524,7 @@ DWORD clust2sect ( /* !=0: sector number, 0: failed - invalid cluster# */ /*-----------------------------------------------------------------------*/ -/* Seek directory index */ +/* Directory handling - Seek directory index */ /*-----------------------------------------------------------------------*/ static @@ -520,25 +541,29 @@ FRESULT dir_seek ( clst = dj->sclust; if (clst == 1 || clst >= dj->fs->max_clust) /* Check start cluster range */ return FR_INT_ERR; + if (!clst && dj->fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ + clst = dj->fs->dirbase; if (clst == 0) { /* Static table */ + dj->clust = clst; if (idx >= dj->fs->n_rootdir) /* Index is out of range */ return FR_INT_ERR; - dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32); + dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32); /* Sector# */ } else { /* Dynamic table */ - ic = SS(dj->fs) / 32 * dj->fs->csize; /* Indexes per cluster */ + ic = SS(dj->fs) / 32 * dj->fs->csize; /* Entries per cluster */ while (idx >= ic) { /* Follow cluster chain */ - clst = get_cluster(dj->fs, clst); /* Get next cluster */ + clst = get_fat(dj->fs, clst); /* Get next cluster */ if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ if (clst < 2 || clst >= dj->fs->max_clust) /* Reached to end of table or int error */ return FR_INT_ERR; idx -= ic; } dj->clust = clst; - dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32); + dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32); /* Sector# */ } - dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32; + + dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32; /* Ptr to the entry in the sector */ return FR_OK; /* Seek succeeded */ } @@ -547,7 +572,7 @@ FRESULT dir_seek ( /*-----------------------------------------------------------------------*/ -/* Move directory index next */ +/* Directory handling - Move directory index next */ /*-----------------------------------------------------------------------*/ static @@ -567,16 +592,16 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an if (!(i % (SS(dj->fs) / 32))) { /* Sector changed? */ dj->sect++; /* Next sector */ - if (dj->sclust == 0) { /* Static table */ + if (dj->clust == 0) { /* Static table */ if (i >= dj->fs->n_rootdir) /* Report EOT when end of table */ return FR_NO_FILE; } else { /* Dynamic table */ if (((i / (SS(dj->fs) / 32)) & (dj->fs->csize - 1)) == 0) { /* Cluster changed? */ - clst = get_cluster(dj->fs, dj->clust); /* Get next cluster */ + clst = get_fat(dj->fs, dj->clust); /* Get next cluster */ if (clst <= 1) return FR_INT_ERR; if (clst == 0xFFFFFFFF) return FR_DISK_ERR; - if (clst >= dj->fs->max_clust) { /* When it reached end of dinamic table */ + if (clst >= dj->fs->max_clust) { /* When it reached end of dynamic table */ #if !_FS_READONLY BYTE c; if (!streach) return FR_NO_FILE; /* When do not streach, report EOT */ @@ -614,7 +639,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an /*-----------------------------------------------------------------------*/ -/* Test/Pick/Fit an LFN segment from/to directory entry */ +/* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ /*-----------------------------------------------------------------------*/ #if _USE_LFN static @@ -622,27 +647,24 @@ const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* Offset of LFN char static -BOOL test_lfn ( /* TRUE:Matched, FALSE:Not matched */ +BOOL cmp_lfn ( /* TRUE:Matched, FALSE:Not matched */ WCHAR *lfnbuf, /* Pointer to the LFN to be compared */ BYTE *dir /* Pointer to the directory entry containing a part of LFN */ ) { int i, s; - WCHAR wc1, wc2; + WCHAR wc; - i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13; /* Offset in the LFN buffer */ + i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13; /* Get offset in the LFN buffer */ s = 0; do { - if (i >= _MAX_LFN) return FALSE; /* Out of buffer range? */ - wc1 = LD_WORD(dir+LfnOfs[s]); /* Get both characters to compare */ - wc2 = lfnbuf[i++]; - if (IsLower(wc1)) wc1 -= 0x20; /* Compare it (ignore case) */ - if (IsLower(wc2)) wc2 -= 0x20; - if (wc1 != wc2) return FALSE; - } while (++s < 13 && wc1); /* Repeat until last char or a NUL char is processed */ + wc = ff_wtoupper(LD_WORD(dir+LfnOfs[s])); /* Get an LFN character */ + if (i >= _MAX_LFN || wc != ff_wtoupper(lfnbuf[i++])) /* Compare it with the reference character */ + return FALSE; + } while (++s < 13 && wc); /* Repeat until all chars in the entry or a NUL char is processed */ - return TRUE; /* The LFN entry matched */ + return TRUE; /* The LFN entry matched */ } @@ -654,18 +676,23 @@ BOOL pick_lfn ( /* TRUE:Succeeded, FALSE:Buffer overflow */ ) { int i, s; - WCHAR wchr; + WCHAR wc; - i = ((dir[LDIR_Ord] & 0xBF) - 1) * 13; /* Offset in the LFN buffer */ + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + s = 0; do { - wchr = LD_WORD(dir+LfnOfs[s]); /* Get an LFN char */ - if (!wchr) break; /* End of LFN? */ - if (i >= _MAX_LFN) return FALSE; /* Buffer overflow */ - lfnbuf[i++] = wchr; /* Store it */ + if (i >= _MAX_LFN) return FALSE; /* Buffer overflow? */ + wc = LD_WORD(dir+LfnOfs[s]); /* Get an LFN char */ + if (!wc) break; /* End of LFN? */ + lfnbuf[i++] = wc; /* Store it */ } while (++s < 13); /* Repeat until last char is copied */ - if (dir[LDIR_Ord] & 0x40) lfnbuf[i] = 0; /* Put terminator if last LFN entry */ + + if (dir[LDIR_Ord] & 0x40) { /* Put terminator if it is the last LFN part */ + if (i >= _MAX_LFN) return FALSE; /* Buffer overflow? */ + lfnbuf[i] = 0; + } return TRUE; } @@ -681,7 +708,7 @@ void fit_lfn ( ) { int i, s; - WCHAR wchr; + WCHAR wc; dir[LDIR_Chksum] = sum; /* Set check sum */ @@ -689,14 +716,14 @@ void fit_lfn ( dir[LDIR_Type] = 0; ST_WORD(dir+LDIR_FstClusLO, 0); - i = (ord - 1) * 13; /* Offset in the LFN buffer */ - s = wchr = 0; + i = (ord - 1) * 13; /* Get offset in the LFN buffer */ + s = wc = 0; do { - if (wchr != 0xFFFF) wchr = lfnbuf[i++]; /* Get an effective char */ - ST_WORD(dir+LfnOfs[s], wchr); /* Put it */ - if (!wchr) wchr = 0xFFFF; /* Padding chars following last char */ + if (wc != 0xFFFF) wc = lfnbuf[i++]; /* Get an effective char */ + ST_WORD(dir+LfnOfs[s], wc); /* Put it */ + if (!wc) wc = 0xFFFF; /* Padding chars following last char */ } while (++s < 13); - if (wchr == 0xFFFF || !lfnbuf[i]) ord |= 0x40;/* Bottom LFN part is the start of LFN sequence */ + if (wc == 0xFFFF || !lfnbuf[i]) ord |= 0x40; /* Bottom LFN part is the start of LFN sequence */ dir[LDIR_Ord] = ord; /* Set the LFN order */ } @@ -771,7 +798,7 @@ BYTE sum_sfn ( /*-----------------------------------------------------------------------*/ -/* Find an object in the directory */ +/* Directory handling - Find an object in the directory */ /*-----------------------------------------------------------------------*/ static @@ -780,22 +807,26 @@ FRESULT dir_find ( ) { FRESULT res; - BYTE a, c, lfen, ord, sum, *dir; - + BYTE c, *dir; +#if _USE_LFN + BYTE a, lfen, ord, sum; +#endif res = dir_seek(dj, 0); /* Rewind directory object */ if (res != FR_OK) return res; - ord = sum = 0xFF; lfen = *(dj->fn+11) & 1; +#if _USE_LFN + ord = sum = 0xFF; lfen = *(dj->fn+11) & NS_LOSS; +#endif do { res = move_window(dj->fs, dj->sect); if (res != FR_OK) break; dir = dj->dir; /* Ptr to the directory entry of current index */ c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ - a = dir[DIR_Attr] & AM_MASK; #if _USE_LFN /* LFN configuration */ - if (c == 0xE5 || c == '.' || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + a = dir[DIR_Attr] & AM_MASK; + if (c == 0xE5 || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ ord = 0xFF; } else { if (a == AM_LFN) { /* An LFN entry is found */ @@ -806,22 +837,21 @@ FRESULT dir_find ( dj->lfn_idx = dj->index; } /* Check LFN validity. Compare LFN if it is out of 8.3 format */ - ord = (c == ord && sum == dir[LDIR_Chksum] && (!lfen || test_lfn(dj->lfn, dir))) ? ord - 1 : 0xFF; + ord = (c == ord && sum == dir[LDIR_Chksum] && (!lfen || cmp_lfn(dj->lfn, dir))) ? ord - 1 : 0xFF; } } else { /* An SFN entry is found */ - if (ord || sum != sum_sfn(dir)) { /* Did not LFN match? */ + if (ord || sum != sum_sfn(dir)) /* Did not LFN match? */ dj->lfn_idx = 0xFFFF; - ord = 0xFF; - } if (lfen) { /* Match LFN if it is out of 8.3 format */ if (ord == 0) break; } else { /* Match SFN if LFN is in 8.3 format */ if (!mem_cmp(dir, dj->fn, 11)) break; } + ord = 0xFF; } } -#else /* Non LFN configuration */ - if (c != 0xE5 && c != '.' && !(a & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ +#else /* Non LFN configuration */ + if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ break; #endif res = dir_next(dj, FALSE); /* Next entry */ @@ -836,17 +866,18 @@ FRESULT dir_find ( /*-----------------------------------------------------------------------*/ /* Read an object from the directory */ /*-----------------------------------------------------------------------*/ -#if _FS_MINIMIZE <= 2 +#if _FS_MINIMIZE <= 1 static FRESULT dir_read ( - DIR *dj /* Pointer to the directory object to store read object name */ + DIR *dj /* Pointer to the directory object that pointing the entry to be read */ ) { FRESULT res; - BYTE a, c, ord, sum, *dir; + BYTE c, *dir; +#if _USE_LFN + BYTE a, ord = 0xFF, sum = 0xFF; +#endif - - ord = sum = 0xFF; res = FR_NO_FILE; while (dj->sect) { res = move_window(dj->fs, dj->sect); @@ -854,9 +885,9 @@ FRESULT dir_read ( dir = dj->dir; /* Ptr to the directory entry of current index */ c = dir[DIR_Name]; if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ - a = dir[DIR_Attr] & AM_MASK; #if _USE_LFN /* LFN configuration */ - if (c == 0xE5 || c == '.' || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + a = dir[DIR_Attr] & AM_MASK; + if (c == 0xE5 || (!_FS_RPATH && c == '.') || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ ord = 0xFF; } else { if (a == AM_LFN) { /* An LFN entry is found */ @@ -873,8 +904,8 @@ FRESULT dir_read ( break; } } -#else /* Non LFN configuration */ - if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */ +#else /* Non LFN configuration */ + if (c != 0xE5 && (_FS_RPATH || c != '.') && !(dir[DIR_Attr] & AM_VOL)) /* Is it a valid entry? */ break; #endif res = dir_next(dj, FALSE); /* Next entry */ @@ -900,15 +931,18 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many { FRESULT res; BYTE c, *dir; - #if _USE_LFN /* LFN configuration */ WORD n, ne, is; BYTE sn[12], *fn, sum; WCHAR *lfn; + fn = dj->fn; lfn = dj->lfn; mem_cpy(sn, fn, 12); - if (sn[11] & 1) { /* When LFN is out of 8.3 format, generate a numbered name */ + + if (_FS_RPATH && (sn[11] & NS_DOT)) return FR_INVALID_NAME; /* Cannot create dot entry */ + + if (sn[11] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ fn[11] = 0; dj->lfn = NULL; /* Find only SFN */ for (n = 1; n < 100; n++) { gen_numname(fn, sn, lfn, n); /* Generate a numbered name */ @@ -919,11 +953,12 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ fn[11] = sn[11]; dj->lfn = lfn; } - if (sn[11] & 2) { /* When eliminate LFN, reserve only an SFN entry. */ - ne = 1; - } else { /* Otherwise reserve an SFN + LFN entries. */ + + if (sn[11] & NS_LFN) { /* When LFN is to be created, reserve reserve an SFN + LFN entries. */ for (ne = 0; lfn[ne]; ne++) ; ne = (ne + 25) / 13; + } else { /* Otherwise reserve only an SFN entry. */ + ne = 1; } /* Reserve contiguous entries */ @@ -933,7 +968,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many do { res = move_window(dj->fs, dj->sect); if (res != FR_OK) break; - c = *dj->dir; /* Check the entry status */ + c = *dj->dir; /* Check the entry status */ if (c == 0xE5 || c == 0) { /* Is it a blank entry? */ if (n == 0) is = dj->index; /* First index of the contigulus entry */ if (++n == ne) break; /* A contiguous entry that requiered count is found */ @@ -975,7 +1010,7 @@ FRESULT dir_register ( /* FR_OK:Successful, FR_DENIED:No free entry or too many res = move_window(dj->fs, dj->sect); if (res == FR_OK) { dir = dj->dir; - mem_set(dir, 0, 32); /* Clean the entry */ + mem_set(dir, 0, 32); /* Clean the entry */ mem_cpy(dir, dj->fn, 11); /* Put SFN */ dir[DIR_NTres] = *(dj->fn+11) & 0x18; /* Put NT flag */ dj->fs->wflag = 1; @@ -999,7 +1034,6 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ ) { FRESULT res; - #if _USE_LFN /* LFN configuration */ WORD i; @@ -1009,10 +1043,10 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ do { res = move_window(dj->fs, dj->sect); if (res != FR_OK) break; - *dj->dir = 0xE5; /* Mark the entry "deleted" */ + *dj->dir = 0xE5; /* Mark the entry "deleted" */ dj->fs->wflag = 1; - if (dj->index >= i) break; /* When SFN is deleted, all entries of the object is deleted. */ - res = dir_next(dj, FALSE); /* Next entry */ + if (dj->index >= i) break; /* When reached SFN, all entries of the object has been deleted. */ + res = dir_next(dj, FALSE); /* Next entry */ } while (res == FR_OK); if (res == FR_NO_FILE) res = FR_INT_ERR; } @@ -1022,7 +1056,7 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ if (res == FR_OK) { res = move_window(dj->fs, dj->sect); if (res == FR_OK) { - *dj->dir = 0xE5; /* Mark the entry "deleted" */ + *dj->dir = 0xE5; /* Mark the entry "deleted" */ dj->fs->wflag = 1; } } @@ -1039,45 +1073,61 @@ FRESULT dir_remove ( /* FR_OK: Successful, FR_DISK_ERR: A disk error */ /* Pick a segment and create the object name in directory form */ /*-----------------------------------------------------------------------*/ + static FRESULT create_name ( DIR *dj, /* Pointer to the directory object */ - const char **path /* Pointer to pointer to the segment in the path string */ + const XCHAR **path /* Pointer to pointer to the segment in the path string */ ) { -#if _USE_LFN - BYTE c, b, cf, *sfn; +#ifdef _EXCVT + static const BYTE cvt[] = _EXCVT; +#endif +#if _USE_LFN /* LFN configuration */ + BYTE b, cf; WCHAR w, *lfn; int i, ni, si, di; - const char *p; + const XCHAR *p; /* Create LFN in Unicode */ si = di = 0; p = *path; lfn = dj->lfn; for (;;) { - w = (BYTE)p[si++]; /* Get a character */ - if (w < ' ' || w == '/' || w == '\\') break; /* Break on end of segment */ - if (IsDBCS1(w)) { /* If it is DBC 1st byte */ - c = p[si++]; /* Get 2nd byte */ - if (!IsDBCS2(c)) /* Reject invalid DBC */ + w = p[si++]; /* Get a character */ + if (w < L' ' || w == L'/' || w == L'\\') break; /* Break on end of segment */ + if (di >= _MAX_LFN) /* Reject too long name */ + return FR_INVALID_NAME; +#if !_LFN_UNICODE + w &= 0xFF; + if (IsDBCS1(w)) { /* If it is a DBC 1st byte */ + BYTE c = p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(c)) /* Reject invalid code for DBC */ return FR_INVALID_NAME; w = (w << 8) + c; - } else { - if (chk_chr("\"*:<>\?|\x7F", w)) /* Reject unallowable chars for LFN */ - return FR_INVALID_NAME; } - w = ff_convert(w, 1); /* Convert OEM to Unicode, store it */ - if (!w || di >= _MAX_LFN) /* Reject invalid code or too long name */ + w = ff_convert(w, 1); /* Convert OEM to Unicode */ + if (!w) return FR_INVALID_NAME; /* Reject invalid code */ +#endif + if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) /* Reject unallowable chars for LFN */ return FR_INVALID_NAME; - lfn[di++] = w; + lfn[di++] = w; /* Store the Unicode char */ } *path = &p[si]; /* Rerurn pointer to the next segment */ - cf = (w < ' ') ? 4 : 0; /* Set last segment flag if end of path */ - + cf = (w < L' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ +#if _FS_RPATH + if ((di == 1 && lfn[di - 1] == L'.') || /* Is this a dot entry? */ + (di == 2 && lfn[di - 1] == L'.' && lfn[di - 2] == L'.')) { + lfn[di] = 0; + for (i = 0; i < 11; i++) + dj->fn[i] = (i < di) ? '.' : ' '; + dj->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif while (di) { /* Strip trailing spaces and dots */ w = lfn[di - 1]; - if (w != ' ' && w != '.') break; + if (w != L' ' && w != L'.') break; di--; } if (!di) return FR_INVALID_NAME; /* Reject null string */ @@ -1085,38 +1135,47 @@ FRESULT create_name ( lfn[di] = 0; /* LFN is created */ /* Create SFN in directory form */ - sfn = dj->fn; - mem_set(sfn, ' ', 11); - for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ - if (si) cf |= 1; + mem_set(dj->fn, ' ', 11); + for (si = 0; lfn[si] == L' ' || lfn[si] == L'.'; si++) ; /* Strip leading spaces and dots */ + if (si) cf |= NS_LOSS | NS_LFN; while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ b = i = 0; ni = 8; for (;;) { w = lfn[si++]; /* Get an LFN char */ - if (w == 0) break; /* Break when enf of the LFN */ - if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ - cf |= 1; continue; + if (!w) break; /* Break when enf of the LFN */ + if (w == L' ' || (w == L'.' && si != di)) { /* Remove spaces and dots */ + cf |= NS_LOSS | NS_LFN; continue; } - if (i >= ni || si == di) { /* Here is extension or end of SFN */ - if (ni == 11) { /* Extension is longer than 3 bytes */ - cf |= 1; break; + + if (i >= ni || si == di) { /* Extension or end of SFN */ + if (ni == 11) { /* Long extension */ + cf |= NS_LOSS | NS_LFN; break; } - if (si != di) cf |= 1; /* File name is longer than 8 bytes */ + if (si != di) cf |= NS_LOSS | NS_LFN; /* File name is longer than 8 bytes */ if (si > di) break; /* No extension */ si = di; i = 8; ni = 11; /* Enter extension section */ b <<= 2; continue; } - w = ff_convert(w, 0); /* Unicode -> OEM code */ - if (w >= 0x80) cf |= 0x20; /* If there is any extended char, force create an LFN */ - if (w >= 0x100) { /* Double byte char */ + + if (w >= 0x80) { /* Non ASCII char */ +#ifdef _EXCVT + w = ff_convert(w, 0); /* Unicode -> OEM code */ + if (w) w = cvt[w - 0x80]; /* Convert extend char (SBCS) */ +#else + w = ff_convert(ff_wtoupper(w), 0); /* Unicode (Caps) -> OEM code */ +#endif + cf |= NS_LFN; /* Force create an LFN */ + } + + if (_DF1S && w >= 0x100) { /* Double byte char */ if (i >= ni - 1) { - cf |= 1; i = ni; continue; + cf |= NS_LOSS | NS_LFN; i = ni; continue; } - sfn[i++] = (BYTE)(w >> 8); + dj->fn[i++] = (BYTE)(w >> 8); } else { /* Single byte char */ - if (chk_chr("+,;[=]", w)) { /* Replace unallowable chars for SFN */ - w = '_'; cf |= 1; + if (!w || chk_chr("+,;[=]", w)) { /* Replace unallowable chars for SFN */ + w = '_'; cf |= NS_LOSS | NS_LFN; /* Lossy conversion */ } else { if (IsUpper(w)) { /* Large capital */ b |= 2; @@ -1127,21 +1186,24 @@ FRESULT create_name ( } } } - sfn[i++] = (BYTE)w; + dj->fn[i++] = (BYTE)w; } - if (sfn[0] == 0xE5) sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */ + + if (dj->fn[0] == 0xE5) dj->fn[0] = 0x05; /* If the first char collides with 0xE5, replace it with 0x05 */ if (ni == 8) b <<= 2; - if ((cf & 0x21) == 0) { /* When LFN is in 8.3 format without extended char, NT flags are created */ - if ((b & 0x03) == 0x01) cf |= 0x10; /* NT flag (Extension has only small capital) */ - if ((b & 0x0C) == 0x04) cf |= 0x08; /* NT flag (Filename has only small capital) */ - if ((b & 0x0C) != 0x0C && (b & 0x03) != 0x03) cf |= 2; /* Eliminate LFN when non composite capitals */ + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) /* Create LFN entry when there are composite capitals */ + cf |= NS_LFN; + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended char, NT flags are created */ + if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ } - sfn[11] = cf; /* SFN is created */ + dj->fn[11] = cf; /* SFN is created */ -#else - BYTE c, d, b, *sfn; + +#else /* Non-LFN configuration */ + BYTE b, c, d, *sfn; int ni, si, i; const char *p; @@ -1150,6 +1212,19 @@ FRESULT create_name ( mem_set(sfn, ' ', 11); si = i = b = 0; ni = 8; p = *path; +#if _FS_RPATH + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c >= ' ') return FR_INVALID_NAME; + *path = &p[si]; /* Rerurn pointer to the next segment */ + sfn[11] = (c < ' ') ? NS_LAST|NS_DOT : NS_DOT; /* Set last segment flag if end of path */ + return FR_OK; + } +#endif for (;;) { c = p[si++]; if (c < ' ' || c == '/' || c == '\\') break; /* Break on end of segment */ @@ -1158,7 +1233,16 @@ FRESULT create_name ( i = 8; ni = 11; b <<= 2; continue; } - if (c >= 0x80) b |= 3; /* If there is any extended char, eliminate NT flag */ + if (c >= 0x80) { /* Extended char */ +#ifdef _EXCVT + c = cvt[c - 0x80]; /* Convert extend char (SBCS) */ +#else + b |= 3; /* Eliminate NT flag if ext char is exist */ +#if !_DF1S /* ASCII only cfg */ + return FR_INVALID_NAME; +#endif +#endif + } if (IsDBCS1(c)) { /* If it is DBC 1st byte */ d = p[si++]; /* Get 2nd byte */ if (!IsDBCS2(d) || i >= ni - 1) /* Reject invalid DBC */ @@ -1166,7 +1250,7 @@ FRESULT create_name ( sfn[i++] = c; sfn[i++] = d; } else { - if (chk_chr(" +,;[=]\"*:<>\?|\x7F", c)) /* Reject unallowable chrs for SFN */ + if (chk_chr(" \"*+,[=]|\x7F", c)) /* Reject unallowable chrs for SFN */ return FR_INVALID_NAME; if (IsUpper(c)) { b |= 2; @@ -1179,14 +1263,14 @@ FRESULT create_name ( } } *path = &p[si]; /* Rerurn pointer to the next segment */ - c = (c < ' ') ? 4 : 0; /* Set last segment flag if end of path */ + c = (c < ' ') ? NS_LAST : 0; /* Set last segment flag if end of path */ if (!i) return FR_INVALID_NAME; /* Reject null string */ if (sfn[0] == 0xE5) sfn[0] = 0x05; /* When first char collides with 0xE5, replace it with 0x05 */ if (ni == 8) b <<= 2; - if ((b & 0x03) == 0x01) c |= 0x10; /* NT flag (Extension has only small capital) */ - if ((b & 0x0C) == 0x04) c |= 0x08; /* NT flag (Filename has only small capital) */ + if ((b & 0x03) == 0x01) c |= NS_EXT; /* NT flag (Extension has only small capital) */ + if ((b & 0x0C) == 0x04) c |= NS_BODY; /* NT flag (Filename has only small capital) */ sfn[11] = c; /* Store NT flag, File name is created */ #endif @@ -1210,20 +1294,23 @@ void get_fileinfo ( /* No return code */ int i; BYTE c, nt, *dir; char *p; +#if _USE_LFN + XCHAR *tp; +#endif p = fno->fname; if (dj->sect) { dir = dj->dir; nt = dir[DIR_NTres]; /* NT flag */ - for (i = 0; i < 8; i++) { /* Copy file name body */ + for (i = 0; i < 8; i++) { /* Copy name body */ c = dir[i]; if (c == ' ') break; if (c == 0x05) c = 0xE5; if ((nt & 0x08) && IsUpper(c)) c += 0x20; *p++ = c; } - if (dir[8] != ' ') { /* Copy file name extension */ + if (dir[8] != ' ') { /* Copy name extension */ *p++ = '.'; for (i = 8; i < 11; i++) { c = dir[i]; @@ -1240,23 +1327,25 @@ void get_fileinfo ( /* No return code */ *p = 0; #if _USE_LFN - p = fno->lfname; - if (p) { - WCHAR wchr, *lfn; + tp = fno->lfname; + if (tp) { + WCHAR w, *lfn; i = 0; if (dj->sect && dj->lfn_idx != 0xFFFF) {/* Get LFN if available */ lfn = dj->lfn; - while ((wchr = *lfn++) != 0) { /* Get an LFN char */ - wchr = ff_convert(wchr, 0); /* Unicode -> OEM code */ - if (!wchr) { i = 0; break; } /* Conversion error, no LFN */ - if (_DF1S && wchr >= 0x100) /* Put 1st byte if it is a DBC */ - p[i++] = (char)(wchr >> 8); - p[i++] = (char)wchr; - if (i >= fno->lfsize) { i = 0; break; } /* Buffer overrun, no LFN */ + while ((w = *lfn++) != 0) { /* Get an LFN char */ +#if !_LFN_UNICODE + w = ff_convert(w, 0); /* Unicode -> OEM conversion */ + if (!w) { i = 0; break; } /* Could not convert, no LFN */ + if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC */ + tp[i++] = (XCHAR)(w >> 8); + if (i >= fno->lfsize - 1) { i = 0; break; } /* Buffer overrun, no LFN */ +#endif + tp[i++] = (XCHAR)w; } } - p[i] = 0; /* Terminator */ + tp[i] = 0; /* Terminator */ } #endif } @@ -1272,19 +1361,26 @@ void get_fileinfo ( /* No return code */ static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ DIR *dj, /* Directory object to return last directory and found object */ - const char *path /* Full-path string to find a file or directory */ + const XCHAR *path /* Full-path string to find a file or directory */ ) { FRESULT res; BYTE *dir, last; - if (*path == '/' || *path == '\\' ) path++; /* Strip heading separator */ +#if _FS_RPATH + if (*path == '/' || *path == '\\') { /* There is a heading separator */ + path++; dj->sclust = 0; /* Strip it and start from the root dir */ + } else { /* No heading saparator */ + dj->sclust = dj->fs->cdir; /* Start from the current dir */ + } +#else + if (*path == '/' || *path == '\\') /* Strip heading separator if exist */ + path++; + dj->sclust = 0; /* Start from the root dir */ +#endif - dj->sclust = /* Set start directory (root dir) */ - (dj->fs->fs_type == FS_FAT32) ? dj->fs->dirbase : 0; - - if ((BYTE)*path < ' ') { /* Null path means the root directory */ + if ((UINT)*path < ' ') { /* Null path means the start directory itself */ res = dir_seek(dj, 0); dj->dir = NULL; @@ -1293,7 +1389,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ res = create_name(dj, &path); /* Get a segment */ if (res != FR_OK) break; res = dir_find(dj); /* Find it */ - last = *(dj->fn+11) & 4; + last = *(dj->fn+11) & NS_LAST; if (res != FR_OK) { /* Could not find the object */ if (res == FR_NO_FILE && !last) res = FR_NO_PATH; @@ -1324,14 +1420,17 @@ BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2: DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ ) { + static const char fatstr[] = "FAT"; + + if (disk_read(fs->drive, fs->win, sect, 1) != RES_OK) /* Load boot record */ return 3; - if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ + if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) /* Check record signature (always placed at offset 510 even if the sector size is >512) */ return 2; - if (!mem_cmp(&fs->win[BS_FilSysType], "FAT", 3)) /* Check FAT signature */ + if (!mem_cmp(&fs->win[BS_FilSysType], fatstr, 3)) /* Check FAT signature */ return 0; - if (!mem_cmp(&fs->win[BS_FilSysType32], "FAT32", 5) && !(fs->win[BPB_ExtFlags] & 0x80)) + if (!mem_cmp(&fs->win[BS_FilSysType32], fatstr, 3) && !(fs->win[BPB_ExtFlags] & 0x80)) return 0; return 1; @@ -1346,50 +1445,55 @@ BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2: static FRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */ - const char **path, /* Pointer to pointer to the path name (drive number) */ + const XCHAR **path, /* Pointer to pointer to the path name (drive number) */ FATFS **rfs, /* Pointer to pointer to the found file system object */ BYTE chk_wp /* !=0: Check media write protection for write access */ ) { FRESULT res; - BYTE vol, fmt, *tbl; + BYTE fmt, *tbl; + UINT vol; DSTATUS stat; DWORD bsect, fsize, tsect, mclst; - const char *p = *path; + const XCHAR *p = *path; FATFS *fs; /* Get logical drive number from the path name */ - vol = p[0] - '0'; /* Is there a drive number? */ - if (vol <= 9 && p[1] == ':') { - p += 2; /* Found a drive number, get and strip it */ - *path = p; /* Return pointer to the path name */ - } else { - vol = 0; /* No drive number is given, use drive number 0 as default */ + vol = p[0] - '0'; /* Is there a drive number? */ + if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ + p += 2; *path = p; /* Return pointer to the path name */ + } else { /* No drive number is given */ +#if _FS_RPATH + vol = Drive; /* Use current drive */ +#else + vol = 0; /* Use drive 0 */ +#endif } - /* Check if the logical drive number is valid or not */ - if (vol >= _DRIVES) return FR_INVALID_DRIVE; /* Is the drive number valid? */ - *rfs = fs = FatFs[vol]; /* Returen pointer to the corresponding file system object */ - if (!fs) return FR_NOT_ENABLED; /* Is the file system object registered? */ + /* Check if the logical drive is valid or not */ + if (vol >= _DRIVES) /* Is the drive number valid? */ + return FR_INVALID_DRIVE; + *rfs = fs = FatFs[vol]; /* Returen pointer to the corresponding file system object */ + if (!fs) return FR_NOT_ENABLED; /* Is the file system object registered? */ - ENTER_FF(fs); /* Lock file system */ + ENTER_FF(fs); /* Lock file system */ - if (fs->fs_type) { /* If the logical drive has been mounted */ + if (fs->fs_type) { /* If the logical drive has been mounted */ stat = disk_status(fs->drive); - if (!(stat & STA_NOINIT)) { /* and physical drive is kept initialized (has not been changed), */ + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ #if !_FS_READONLY if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ return FR_WRITE_PROTECTED; #endif - return FR_OK; /* The file system object is valid */ + return FR_OK; /* The file system object is valid */ } } - /* The logical drive must be re-mounted. Following code attempts to mount the volume */ + /* The logical drive must be mounted. Following code attempts to mount the volume */ fs->fs_type = 0; /* Clear the file system object */ - fs->drive = LD2PD(vol); /* Bind the logical drive and a physical drive */ + fs->drive = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */ stat = disk_initialize(fs->drive); /* Initialize low level disk I/O layer */ if (stat & STA_NOINIT) /* Check if the drive is ready */ return FR_NOT_READY; @@ -1398,7 +1502,7 @@ FRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */ return FR_NO_FILESYSTEM; #endif #if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ + if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ return FR_WRITE_PROTECTED; #endif /* Search FAT partition on the drive */ @@ -1431,8 +1535,8 @@ FRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */ ) / fs->csize + 2; fmt = FS_FAT12; /* Determine the FAT sub type */ - if (mclst >= 0xFF7) fmt = FS_FAT16; /* Number of clusters >= 0xFF5 */ - if (mclst >= 0xFFF7) fmt = FS_FAT32; /* Number of clusters >= 0xFFF5 */ + if (mclst >= 0xFF7) fmt = FS_FAT16; /* Number of clusters >= 0xFF5 */ + if (mclst >= 0xFFF7) fmt = FS_FAT32; /* Number of clusters >= 0xFFF5 */ if (fmt == FS_FAT32) fs->dirbase = LD_DWORD(fs->win+BPB_RootClus); /* Root directory start cluster */ @@ -1446,8 +1550,8 @@ FRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */ fs->wflag = 0; /* Get fsinfo if needed */ if (fmt == FS_FAT32) { + fs->fsi_flag = 0; fs->fsi_sector = bsect + LD_WORD(fs->win+BPB_FSInfo); - fs->fsi_flag = 0; if (disk_read(fs->drive, fs->win, fs->fsi_sector, 1) == RES_OK && LD_WORD(fs->win+BS_55AA) == 0xAA55 && LD_DWORD(fs->win+FSI_LeadSig) == 0x41615252 && @@ -1457,9 +1561,12 @@ FRESULT auto_mount ( /* FR_OK(0): successful, !=0: any error occured */ } } #endif - fs->winsect = 0; - fs->fs_type = fmt; /* FAT syb-type */ - fs->id = ++Fsid; /* File system mount ID */ + fs->fs_type = fmt; /* FAT sub-type */ + fs->winsect = 0; /* Invalidate sector cache */ +#if _FS_RPATH + fs->cdir = 0; /* Current directory (root dir) */ +#endif + fs->id = ++Fsid; /* File system mount ID */ res = FR_OK; return res; @@ -1514,11 +1621,11 @@ FRESULT f_mount ( if (vol >= _DRIVES) /* Check if the drive number is valid */ return FR_INVALID_DRIVE; - rfs = FatFs[vol]; /* Get current state */ + rfs = FatFs[vol]; /* Get current fs object */ if (rfs) { #if _FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(fs->sobj)) return FR_INT_ERR; + if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; #endif rfs->fs_type = 0; /* Clear old fs object */ } @@ -1543,7 +1650,7 @@ FRESULT f_mount ( FRESULT f_open ( FIL *fp, /* Pointer to the blank file object */ - const char *path, /* Pointer to the file name */ + const XCHAR *path, /* Pointer to the file name */ BYTE mode /* Access mode and file open mode flags */ ) { @@ -1570,20 +1677,20 @@ FRESULT f_open ( if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { DWORD ps, cl; - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ res = dir_register(&dj); if (res != FR_OK) LEAVE_FF(dj.fs, res); mode |= FA_CREATE_ALWAYS; - dir = dj.dir; + dir = dj.dir; /* Created entry (SFN entry) */ } - else { /* Any object is already existing */ + else { /* Any object is already existing */ if (mode & FA_CREATE_NEW) /* Cannot create new */ LEAVE_FF(dj.fs, FR_EXIST); dir = dj.dir; if (!dir || (dir[DIR_Attr] & (AM_RDO | AM_DIR))) /* Cannot overwrite it (R/O or DIR) */ LEAVE_FF(dj.fs, FR_DENIED); - if (mode & FA_CREATE_ALWAYS) { /* Resize it to zero if needed */ + if (mode & FA_CREATE_ALWAYS) { /* Resize it to zero on over write mode */ cl = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); /* Get start cluster */ ST_WORD(dir+DIR_FstClusHI, 0); /* cluster = 0 */ ST_WORD(dir+DIR_FstClusLO, 0); @@ -1668,7 +1775,7 @@ FRESULT f_read ( if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */ clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->org_clust : get_cluster(fp->fs, fp->curr_clust); + fp->org_clust : get_fat(fp->fs, fp->curr_clust); if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->curr_clust = clst; /* Update current cluster */ @@ -1683,6 +1790,15 @@ FRESULT f_read ( cc = fp->fs->csize - fp->csect; if (disk_read(fp->fs->drive, rbuff, sect, (BYTE)cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); +#if !_FS_READONLY && _FS_MINIMIZE <= 2 +#if _FS_TINY + if (fp->fs->wflag && fp->fs->winsect - sect < cc) /* Replace one of the read sectors with cached data if it contains a dirty sector */ + mem_cpy(rbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), fp->fs->win, SS(fp->fs)); +#else + if ((fp->flag & FA__DIRTY) && fp->dsect - sect < cc) /* Replace one of the read sectors with cached data if it contains a dirty sector */ + mem_cpy(rbuff + ((fp->dsect - sect) * SS(fp->fs)), fp->buf, SS(fp->fs)); +#endif +#endif fp->csect += (BYTE)cc; /* Next sector address in the cluster */ rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ continue; @@ -1692,7 +1808,7 @@ FRESULT f_read ( if (fp->flag & FA__DIRTY) { /* Write sector I/O buffer if needed */ if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA__DIRTY; + fp->flag &= ~FA__DIRTY; } #endif if (fp->dsect != sect) { /* Fill sector buffer with file data */ @@ -1714,7 +1830,6 @@ FRESULT f_read ( #endif } - LEAVE_FF(fp->fs, FR_OK); } @@ -1773,7 +1888,7 @@ FRESULT f_write ( if (fp->flag & FA__DIRTY) { /* Write back data buffer prior to following direct transfer */ if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA__DIRTY; + fp->flag &= ~FA__DIRTY; } #endif sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ @@ -1785,6 +1900,17 @@ FRESULT f_write ( cc = fp->fs->csize - fp->csect; if (disk_write(fp->fs->drive, wbuff, sect, (BYTE)cc) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); +#if _FS_TINY + if (fp->fs->winsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ + mem_cpy(fp->fs->win, wbuff + ((fp->fs->winsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->fs->wflag = 0; + } +#else + if (fp->dsect - sect < cc) { /* Refill sector cache if it gets dirty by the direct write */ + mem_cpy(fp->buf, wbuff + ((fp->dsect - sect) * SS(fp->fs)), SS(fp->fs)); + fp->flag &= ~FA__DIRTY; + } +#endif fp->csect += (BYTE)cc; /* Next sector address in the cluster */ wcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ continue; @@ -1846,7 +1972,7 @@ FRESULT f_sync ( if (fp->flag & FA__DIRTY) { if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK) LEAVE_FF(fp->fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA__DIRTY; + fp->flag &= ~FA__DIRTY; } #endif /* Update the directory entry */ @@ -1857,9 +1983,9 @@ FRESULT f_sync ( ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ ST_WORD(dir+DIR_FstClusLO, fp->org_clust); /* Update start cluster */ ST_WORD(dir+DIR_FstClusHI, fp->org_clust >> 16); - tim = get_fattime(); /* Updated time */ + tim = get_fattime(); /* Updated time */ ST_DWORD(dir+DIR_WrtTime, tim); - fp->flag &= (BYTE)~FA__WRITTEN; + fp->flag &= ~FA__WRITTEN; fp->fs->wflag = 1; res = sync(fp->fs); } @@ -1899,6 +2025,61 @@ FRESULT f_close ( +/*-----------------------------------------------------------------------*/ +/* Change Current Drive/Directory */ +/*-----------------------------------------------------------------------*/ + +#if _FS_RPATH + +FRESULT f_chdrive ( + BYTE drv /* Drive number */ +) +{ + if (drv >= _DRIVES) return FR_INVALID_DRIVE; + + Drive = drv; + + return FR_OK; +} + + + + +FRESULT f_chdir ( + const XCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + NAMEBUF(sfn, lfn); + BYTE *dir; + + + res = auto_mount(&path, &dj.fs, 0); + if (res == FR_OK) { + INITBUF(dj, sfn, lfn); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + dir = dj.dir; /* Pointer to the entry */ + if (!dir) { + dj.fs->cdir = 0; /* No entry (root dir) */ + } else { + if (dir[DIR_Attr] & AM_DIR) /* Reached to the dir */ + dj.fs->cdir = ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) | LD_WORD(dir+DIR_FstClusLO); + else + res = FR_NO_PATH; /* Could not reach the dir (it is a file) */ + } + } + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(dj.fs, res); +} + +#endif + + + #if _FS_MINIMIZE <= 2 /*-----------------------------------------------------------------------*/ /* Seek File R/W Pointer */ @@ -1924,8 +2105,7 @@ FRESULT f_lseek ( ) ofs = fp->fsize; ifptr = fp->fptr; - fp->fptr = 0; fp->csect = 255; - nsect = 0; + fp->fptr = nsect = 0; fp->csect = 255; if (ofs > 0) { bcs = (DWORD)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ if (ifptr > 0 && @@ -1955,7 +2135,7 @@ FRESULT f_lseek ( } } else #endif - clst = get_cluster(fp->fs, clst); /* Follow cluster chain if not in write mode */ + clst = get_fat(fp->fs, clst); /* Follow cluster chain if not in write mode */ if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); if (clst <= 1 || clst >= fp->fs->max_clust) ABORT(fp->fs, FR_INT_ERR); fp->curr_clust = clst; @@ -1972,13 +2152,13 @@ FRESULT f_lseek ( } } } - if (nsect && nsect != fp->dsect && fp->fptr % SS(fp->fs)) { + if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) { #if !_FS_TINY #if !_FS_READONLY if (fp->flag & FA__DIRTY) { /* Write-back dirty buffer if needed */ if (disk_write(fp->fs->drive, fp->buf, fp->dsect, 1) != RES_OK) ABORT(fp->fs, FR_DISK_ERR); - fp->flag &= (BYTE)~FA__DIRTY; + fp->flag &= ~FA__DIRTY; } #endif if (disk_read(fp->fs->drive, fp->buf, nsect, 1) != RES_OK) @@ -2006,7 +2186,7 @@ FRESULT f_lseek ( FRESULT f_opendir ( DIR *dj, /* Pointer to directory object to create */ - const char *path /* Pointer to the directory path */ + const XCHAR *path /* Pointer to the directory path */ ) { FRESULT res; @@ -2026,14 +2206,13 @@ FRESULT f_opendir ( } else { /* The object is not a directory */ res = FR_NO_PATH; } - } else { /* It is the root dir */ - dj->sclust = (dj->fs->fs_type == FS_FAT32) ? dj->fs->dirbase : 0; } - if (res == FR_OK) res = dir_seek(dj, 0); - dj->id = dj->fs->id; - } else { - if (res == FR_NO_FILE) res = FR_NO_PATH; + if (res == FR_OK) { + dj->id = dj->fs->id; + res = dir_seek(dj, 0); /* Rewind dir */ + } } + if (res == FR_NO_FILE) res = FR_NO_PATH; } LEAVE_FF(dj->fs, res); @@ -2088,7 +2267,7 @@ FRESULT f_readdir ( /*-----------------------------------------------------------------------*/ FRESULT f_stat ( - const char *path, /* Pointer to the file path */ + const XCHAR *path, /* Pointer to the file path */ FILINFO *fno /* Pointer to file information to return */ ) { @@ -2115,6 +2294,74 @@ FRESULT f_stat ( #if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const XCHAR *path, /* Pointer to the logical drive number (root dir) */ + DWORD *nclst, /* Pointer to the variable to return number of free clusters */ + FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ +) +{ + FRESULT res; + DWORD n, clst, sect, stat; + UINT i; + BYTE fat, *p; + + + /* Get drive number */ + res = auto_mount(&path, fatfs, 0); + if (res != FR_OK) LEAVE_FF(*fatfs, res); + + /* If number of free cluster is valid, return it without cluster scan. */ + if ((*fatfs)->free_clust <= (*fatfs)->max_clust - 2) { + *nclst = (*fatfs)->free_clust; + LEAVE_FF(*fatfs, FR_OK); + } + + /* Get number of free clusters */ + fat = (*fatfs)->fs_type; + n = 0; + if (fat == FS_FAT12) { + clst = 2; + do { + stat = get_fat(*fatfs, clst); + if (stat == 0xFFFFFFFF) LEAVE_FF(*fatfs, FR_DISK_ERR); + if (stat == 1) LEAVE_FF(*fatfs, FR_INT_ERR); + if (stat == 0) n++; + } while (++clst < (*fatfs)->max_clust); + } else { + clst = (*fatfs)->max_clust; + sect = (*fatfs)->fatbase; + i = 0; p = 0; + do { + if (!i) { + res = move_window(*fatfs, sect++); + if (res != FR_OK) + LEAVE_FF(*fatfs, res); + p = (*fatfs)->win; + i = SS(*fatfs); + } + if (fat == FS_FAT16) { + if (LD_WORD(p) == 0) n++; + p += 2; i -= 2; + } else { + if (LD_DWORD(p) == 0) n++; + p += 4; i -= 4; + } + } while (--clst); + } + (*fatfs)->free_clust = n; + if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; + *nclst = n; + + LEAVE_FF(*fatfs, FR_OK); +} + + + + /*-----------------------------------------------------------------------*/ /* Truncate File */ /*-----------------------------------------------------------------------*/ @@ -2141,12 +2388,12 @@ FRESULT f_truncate ( res = remove_chain(fp->fs, fp->org_clust); fp->org_clust = 0; } else { /* When truncate a part of the file, remove remaining clusters */ - ncl = get_cluster(fp->fs, fp->curr_clust); + ncl = get_fat(fp->fs, fp->curr_clust); res = FR_OK; if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; if (ncl == 1) res = FR_INT_ERR; if (res == FR_OK && ncl < fp->fs->max_clust) { - res = put_cluster(fp->fs, fp->curr_clust, 0x0FFFFFFF); + res = put_fat(fp->fs, fp->curr_clust, 0x0FFFFFFF); if (res == FR_OK) res = remove_chain(fp->fs, ncl); } } @@ -2159,75 +2406,12 @@ FRESULT f_truncate ( -/*-----------------------------------------------------------------------*/ -/* Get Number of Free Clusters */ -/*-----------------------------------------------------------------------*/ - -FRESULT f_getfree ( - const char *path, /* Pointer to the logical drive number (root dir) */ - DWORD *nclst, /* Pointer to the variable to return number of free clusters */ - FATFS **fatfs /* Pointer to pointer to corresponding file system object to return */ -) -{ - FRESULT res; - DWORD n, clst, sect; - BYTE fat, f, *p; - - - /* Get drive number */ - res = auto_mount(&path, fatfs, 0); - if (res != FR_OK) LEAVE_FF(*fatfs, res); - - /* If number of free cluster is valid, return it without cluster scan. */ - if ((*fatfs)->free_clust <= (*fatfs)->max_clust - 2) { - *nclst = (*fatfs)->free_clust; - LEAVE_FF(*fatfs, FR_OK); - } - - /* Get number of free clusters */ - fat = (*fatfs)->fs_type; - n = 0; - if (fat == FS_FAT12) { - clst = 2; - do { - if ((WORD)get_cluster(*fatfs, clst) == 0) n++; - } while (++clst < (*fatfs)->max_clust); - } else { - clst = (*fatfs)->max_clust; - sect = (*fatfs)->fatbase; - f = 0; p = 0; - do { - if (!f) { - res = move_window(*fatfs, sect++); - if (res != FR_OK) - LEAVE_FF(*fatfs, res); - p = (*fatfs)->win; - } - if (fat == FS_FAT16) { - if (LD_WORD(p) == 0) n++; - p += 2; f += 1; - } else { - if (LD_DWORD(p) == 0) n++; - p += 4; f += 2; - } - } while (--clst); - } - (*fatfs)->free_clust = n; - if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; - *nclst = n; - - LEAVE_FF(*fatfs, FR_OK); -} - - - - /*-----------------------------------------------------------------------*/ /* Delete a File or Directory */ /*-----------------------------------------------------------------------*/ FRESULT f_unlink ( - const char *path /* Pointer to the file or directory path */ + const XCHAR *path /* Pointer to the file or directory path */ ) { FRESULT res; @@ -2242,6 +2426,8 @@ FRESULT f_unlink ( INITBUF(dj, sfn, lfn); res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[11] & NS_DOT)) + res = FR_INVALID_NAME; if (res != FR_OK) LEAVE_FF(dj.fs, res); /* Follow failed */ dir = dj.dir; @@ -2269,7 +2455,7 @@ FRESULT f_unlink ( if (res == FR_OK) res = sync(dj.fs); } - LEAVE_FF(dj.fs, FR_OK); + LEAVE_FF(dj.fs, res); } @@ -2280,7 +2466,7 @@ FRESULT f_unlink ( /*-----------------------------------------------------------------------*/ FRESULT f_mkdir ( - const char *path /* Pointer to the directory path */ + const XCHAR *path /* Pointer to the directory path */ ) { FRESULT res; @@ -2296,6 +2482,8 @@ FRESULT f_mkdir ( INITBUF(dj, sfn, lfn); res = follow_path(&dj, path); /* Follow the file path */ if (res == FR_OK) res = FR_EXIST; /* Any file or directory is already existing */ + if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[11] & NS_DOT)) + res = FR_INVALID_NAME; if (res != FR_NO_FILE) /* Any error occured */ LEAVE_FF(dj.fs, res); @@ -2357,7 +2545,7 @@ FRESULT f_mkdir ( /*-----------------------------------------------------------------------*/ FRESULT f_chmod ( - const char *path, /* Pointer to the file path */ + const XCHAR *path, /* Pointer to the file path */ BYTE value, /* Attribute bits */ BYTE mask /* Attribute mask to change */ ) @@ -2372,6 +2560,8 @@ FRESULT f_chmod ( if (res == FR_OK) { INITBUF(dj, sfn, lfn); res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[11] & NS_DOT)) + res = FR_INVALID_NAME; if (res == FR_OK) { dir = dj.dir; if (!dir) { /* Is it a root directory? */ @@ -2396,7 +2586,7 @@ FRESULT f_chmod ( /*-----------------------------------------------------------------------*/ FRESULT f_utime ( - const char *path, /* Pointer to the file/directory name */ + const XCHAR *path, /* Pointer to the file/directory name */ const FILINFO *fno /* Pointer to the timestamp to be set */ ) { @@ -2410,6 +2600,8 @@ FRESULT f_utime ( if (res == FR_OK) { INITBUF(dj, sfn, lfn); res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[11] & NS_DOT)) + res = FR_INVALID_NAME; if (res == FR_OK) { dir = dj.dir; if (!dir) { /* Root directory */ @@ -2434,8 +2626,8 @@ FRESULT f_utime ( /*-----------------------------------------------------------------------*/ FRESULT f_rename ( - const char *path_old, /* Pointer to the old name */ - const char *path_new /* Pointer to the new name */ + const XCHAR *path_old, /* Pointer to the old name */ + const XCHAR *path_new /* Pointer to the new name */ ) { FRESULT res; @@ -2450,6 +2642,8 @@ FRESULT f_rename ( if (res == FR_OK) { dj_new.fs = dj_old.fs; res = follow_path(&dj_old, path_old); /* Check old object */ + if (_FS_RPATH && res == FR_OK && (dj_old.fn[11] & NS_DOT)) + res = FR_INVALID_NAME; } if (res != FR_OK) LEAVE_FF(dj_old.fs, res); /* The old object is not found */ @@ -2464,7 +2658,7 @@ FRESULT f_rename ( if (res == FR_OK) { dir = dj_new.dir; /* Copy object information into new entry */ mem_cpy(dir+13, buf+2, 19); - dir[DIR_Attr] = buf[0]; + dir[DIR_Attr] = buf[0] | AM_ARC; dj_old.fs->wflag = 1; if (dir[DIR_Attr] & AM_DIR) { /* Update .. entry in the directory if needed */ dw = clust2sect(dj_new.fs, (DWORD)LD_WORD(dir+DIR_FstClusHI) | LD_WORD(dir+DIR_FstClusLO)); @@ -2533,7 +2727,7 @@ FRESULT f_forward ( if ((fp->fptr % SS(fp->fs)) == 0) { /* On the sector boundary? */ if (fp->csect >= fp->fs->csize) { /* On the cluster boundary? */ clst = (fp->fptr == 0) ? /* On the top of the file? */ - fp->org_clust : get_cluster(fp->fs, fp->curr_clust); + fp->org_clust : get_fat(fp->fs, fp->curr_clust); if (clst <= 1) ABORT(fp->fs, FR_INT_ERR); if (clst == 0xFFFFFFFF) ABORT(fp->fs, FR_DISK_ERR); fp->curr_clust = clst; /* Update current cluster */ @@ -2580,7 +2774,7 @@ FRESULT f_mkfs ( BYTE fmt, m, *tbl; DWORD b_part, b_fat, b_dir, b_data; /* Area offset (LBA) */ DWORD n_part, n_rsv, n_fat, n_dir; /* Area size */ - DWORD n_clst, n; + DWORD n_clst, d, n; WORD as; FATFS *fs; DSTATUS stat; @@ -2600,25 +2794,26 @@ FRESULT f_mkfs ( stat = disk_initialize(drv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; +#if _MAX_SS != 512 /* Get disk sector size */ + if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK + || SS(fs) > _MAX_SS) + return FR_MKFS_ABORTED; +#endif if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_part) != RES_OK || n_part < MIN_SECTOR) return FR_MKFS_ABORTED; if (n_part > MAX_SECTOR) n_part = MAX_SECTOR; b_part = (!partition) ? 63 : 0; /* Boot sector */ n_part -= b_part; -#if _MAX_SS == 512 + for (d = 512; d <= 32768U && d != allocsize; d <<= 1) ; /* Check validity of the allocation unit size */ + if (d != allocsize) allocsize = 0; if (!allocsize) { /* Auto selection of cluster size */ - for (n = 0; n_part < sstbl[n]; n++) ; + d = n_part; + for (as = SS(fs); as > 512U; as >>= 1) d >>= 1; + for (n = 0; d < sstbl[n]; n++) ; allocsize = cstbl[n]; } -#endif - for (as = 512; as <= 32768U && as != allocsize; as <<= 1); - if (as != allocsize) return FR_MKFS_ABORTED; -#if _MAX_SS != 512 /* Check disk sector size */ - if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK - || SS(fs) > _MAX_SS - || SS(fs) > allocsize) - return FR_MKFS_ABORTED; -#endif + if (allocsize < SS(fs)) allocsize = SS(fs); + allocsize /= SS(fs); /* Number of sectors per cluster */ /* Pre-compute number of clusters and FAT type */ @@ -2664,6 +2859,7 @@ FRESULT f_mkfs ( if (!partition) { DWORD n_disk = b_part + n_part; + mem_set(fs->win, 0, SS(fs)); tbl = fs->win+MBR_Table; ST_DWORD(tbl, 0x00010180); /* Partition start in CHS */ if (n_disk < 63UL * 255 * 1024) { /* Partition end in CHS */ @@ -2683,6 +2879,9 @@ FRESULT f_mkfs ( ST_WORD(tbl+64, 0xAA55); /* Signature */ if (disk_write(drv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + partition = 0xF8; + } else { + partition = 0xF0; } /* Create boot record */ @@ -2699,7 +2898,7 @@ FRESULT f_mkfs ( } else { ST_DWORD(tbl+BPB_TotSec32, n_part); } - tbl[BPB_Media] = 0xF8; /* Media descripter */ + tbl[BPB_Media] = partition; /* Media descripter */ ST_WORD(tbl+BPB_SecPerTrk, 63); /* Number of sectors per track */ ST_WORD(tbl+BPB_NumHeads, 255); /* Number of heads */ ST_DWORD(tbl+BPB_HiddSec, b_part); /* Hidden sectors */ @@ -2721,6 +2920,9 @@ FRESULT f_mkfs ( mem_cpy(tbl+BS_VolLab32, "NO NAME FAT32 ", 19); /* Volume lavel, FAT signature */ } ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature */ + if (SS(fs) > 512U) { + ST_WORD(tbl+SS(fs)-2, 0xAA55); + } if (disk_write(drv, tbl, b_part+0, 1) != RES_OK) return FR_DISK_ERR; if (fmt == FS_FAT32) @@ -2730,7 +2932,8 @@ FRESULT f_mkfs ( for (m = 0; m < N_FATS; m++) { mem_set(tbl, 0, SS(fs)); /* 1st sector of the FAT */ if (fmt != FS_FAT32) { - n = (fmt == FS_FAT12) ? 0x00FFFFF8 : 0xFFFFFFF8; + n = (fmt == FS_FAT12) ? 0x00FFFF00 : 0xFFFFFF00; + n |= partition; ST_DWORD(tbl, n); /* Reserve cluster #0-1 (FAT12/16) */ } else { ST_DWORD(tbl+0, 0xFFFFFFF8); /* Reserve cluster #0-1 (FAT32) */ diff --git a/src/ff.h b/src/ff.h index 26569db..694233f 100644 --- a/src/ff.h +++ b/src/ff.h @@ -1,5 +1,5 @@ /*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module include file R0.07a (C)ChaN, 2009 +/ FatFs - FAT file system module include file R0.07c (C)ChaN, 2009 /----------------------------------------------------------------------------/ / FatFs module is an open source software to implement FAT file system to / small embedded systems. This is a free software and is opened for education, @@ -9,7 +9,7 @@ / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for -/ personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY. +/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY. / * Redistributions of source code must retain the above copyright notice. /----------------------------------------------------------------------------*/ @@ -23,7 +23,7 @@ / /----------------------------------------------------------------------------*/ #ifndef _FATFS -#define _FATFS +#define _FATFS 0x007C #define _WORD_ACCESS 0 /* The _WORD_ACCESS option defines which access method is used to the word @@ -72,42 +72,35 @@ /* To enable f_forward function, set _USE_FORWARD to 1 and set _FS_TINY to 1. */ -#define _DRIVES 1 -/* Number of volumes (logical drives) to be used. */ - - -#define _MAX_SS 512 -/* Maximum sector size to be handled. (512/1024/2048/4096) */ -/* 512 for memroy card and hard disk, 1024 for floppy disk, 2048 for MO disk */ - - -#define _MULTI_PARTITION 0 -/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical -/ drive number and can mount only first primaly partition. When it is set to 1, -/ each volume is tied to the partitions listed in Drives[]. */ - - #define _CODE_PAGE 932 /* The _CODE_PAGE specifies the OEM code page to be used on the target system. -/ When it is non LFN configuration, there is no difference between SBCS code -/ pages. When LFN is enabled, the code page must always be set correctly. -/ 437 - U.S. -/ 720 - Arabic -/ 737 - Greek -/ 775 - Baltic -/ 850 - Multilingual Latin 1 -/ 852 - Latin 2 -/ 855 - Cyrillic -/ 857 - Turkish -/ 858 - Multilingual Latin 1 + Euro -/ 862 - Hebrew -/ 866 - Russian -/ 874 - Thai -/ 932 - Japanese Shift-JIS (DBCS) -/ 936 - Simplified Chinese GBK (DBCS) -/ 949 - Korean (DBCS) -/ 950 - Traditional Chinese Big5 (DBCS) -/ 1258 - Vietnam +/ +/ 932 - Japanese Shift-JIS (DBCS, OEM, Windows) +/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows) +/ 949 - Korean (DBCS, OEM, Windows) +/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows) +/ 1250 - Central Europe (Windows) +/ 1251 - Cyrillic (Windows) +/ 1252 - Latin 1 (Windows) +/ 1253 - Greek (Windows) +/ 1254 - Turkish (Windows) +/ 1255 - Hebrew (Windows) +/ 1256 - Arabic (Windows) +/ 1257 - Baltic (Windows) +/ 1258 - Vietnam (OEM, Windows) +/ 437 - U.S. (OEM) +/ 720 - Arabic (OEM) +/ 737 - Greek (OEM) +/ 775 - Baltic (OEM) +/ 850 - Multilingual Latin 1 (OEM) +/ 858 - Multilingual Latin 1 + Euro (OEM) +/ 852 - Latin 2 (OEM) +/ 855 - Cyrillic (OEM) +/ 866 - Russian (OEM) +/ 857 - Turkish (OEM) +/ 862 - Hebrew (OEM) +/ 874 - Thai (OEM, Windows) +/ 1 - ASCII (Valid for only non LFN cfg.) */ @@ -120,17 +113,38 @@ / 2: Enable LFN with dynamic working buffer on the caller's STACK. / / The working buffer occupies (_MAX_LFN + 1) * 2 bytes. When enable LFN, -/ a Unicode - OEM code conversion function ff_convert() must be added to -/ the project. */ +/ a Unicode handling functions ff_convert() and ff_wtoupper() must be added +/ to the project. */ + + +#define _FS_RPATH 0 +/* When _FS_RPATH is set to 1, relative path feature is enabled and f_chdir, +/ f_chdrive function are available. +/ Note that output of the f_readdir fnction is affected by this option. */ #define _FS_REENTRANT 0 -#define _TIMEOUT 1000 /* Timeout period in unit of time ticks */ -#define _SYNC_t HANDLE /* Type of sync object used on the OS. */ - /* e.g. HANDLE, OS_EVENT*, ID and etc.. */ +#define _TIMEOUT 1000 /* Timeout period in unit of time ticks of the OS */ +#define _SYNC_t HANDLE /* Type of sync object used on the OS. e.g. HANDLE, OS_EVENT*, ID and etc.. */ /* To make the FatFs module re-entrant, set _FS_REENTRANT to 1 and add user -/ provided synchronization handlers, ff_req_grant, ff_rel_grant, -/ ff_del_syncobj and ff_cre_syncobj function to the project. */ +/ provided synchronization handlers, ff_req_grant, ff_rel_grant, ff_del_syncobj +/ and ff_cre_syncobj function to the project. */ + + +#define _DRIVES 1 +/* Number of volumes (logical drives) to be used. */ + + +#define _MAX_SS 512 +/* Maximum sector size to be handled. (512/1024/2048/4096) */ +/* Usually set 512 for memory card and hard disk but 1024 for floppy disk, 2048 for MO disk */ +/* When _MAX_SS > 512, GET_SECTOR_SIZE must be implememted to disk_ioctl() */ + + +#define _MULTI_PARTITION 0 +/* When _MULTI_PARTITION is set to 0, each volume is bound to the same physical +/ drive number and can mount only first primaly partition. When it is set to 1, +/ each volume is tied to the partitions listed in Drives[]. */ @@ -139,116 +153,9 @@ -/* Definitions corresponds to multiple sector size */ +/* DBCS code ranges and SBCS extend char conversion table */ -#if _MAX_SS == 512 -#define SS(fs) 512 -#else -#if _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096 -#define SS(fs) ((fs)->s_size) -#else -#error Sector size must be 512, 1024, 2048 or 4096. -#endif -#endif - - - -/* File system object structure */ - -typedef struct _FATFS { - BYTE fs_type; /* FAT sub type */ - BYTE drive; /* Physical drive number */ - BYTE csize; /* Number of sectors per cluster */ - BYTE n_fats; /* Number of FAT copies */ - BYTE wflag; /* win[] dirty flag (1:must be written back) */ - BYTE pad1; - WORD id; /* File system mount ID */ - WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */ -#if _FS_REENTRANT - _SYNC_t sobj; /* Identifier of sync object */ -#endif -#if _MAX_SS != 512U - WORD s_size; /* Sector size */ -#endif -#if !_FS_READONLY - BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ - BYTE pad2; - DWORD last_clust; /* Last allocated cluster */ - DWORD free_clust; /* Number of free clusters */ - DWORD fsi_sector; /* fsinfo sector */ -#endif - DWORD sects_fat; /* Sectors per fat */ - DWORD max_clust; /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */ - DWORD fatbase; /* FAT start sector */ - DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */ - DWORD database; /* Data start sector */ - DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[_MAX_SS];/* Disk access window for Directory/FAT */ -} FATFS; - - - -/* Directory object structure */ - -typedef struct _DIR { - WORD id; /* Owner file system mount ID */ - WORD index; /* Current index number */ - FATFS* fs; /* Pointer to the owner file system object */ - DWORD sclust; /* Table start cluster (0:Static table) */ - DWORD clust; /* Current cluster */ - DWORD sect; /* Current sector */ - BYTE* dir; /* Pointer to the current SFN entry in the win[] */ - BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ -#if _USE_LFN - WCHAR* lfn; /* Pointer to the LFN working buffer */ - WORD lfn_idx; /* Last matched LFN index (0xFFFF:No LFN) */ -#endif -} DIR; - - - -/* File object structure */ - -typedef struct _FIL { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ - BYTE flag; /* File status flags */ - BYTE csect; /* Sector address in the cluster */ - DWORD fptr; /* File R/W pointer */ - DWORD fsize; /* File size */ - DWORD org_clust; /* File start cluster */ - DWORD curr_clust; /* Current cluster */ - DWORD dsect; /* Current data sector */ -#if !_FS_READONLY - DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Ponter to the directory entry in the window */ -#endif -#if !_FS_TINY - BYTE buf[_MAX_SS];/* File R/W buffer */ -#endif -} FIL; - - - -/* File status structure */ - -typedef struct _FILINFO { - DWORD fsize; /* File size */ - WORD fdate; /* Last modified date */ - WORD ftime; /* Last modified time */ - BYTE fattrib; /* Attribute */ - char fname[13]; /* Short file name (8.3 format) */ -#if _USE_LFN - char *lfname; /* Pointer to the LFN buffer */ - int lfsize; /* Size of LFN buffer [bytes] */ -#endif -} FILINFO; - - - -/* DBCS code ranges */ - -#if _CODE_PAGE == 932 /* CP932 (Japanese Shift-JIS) */ +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ #define _DF1S 0x81 /* DBC 1st byte range 1 start */ #define _DF1E 0x9F /* DBC 1st byte range 1 end */ #define _DF2S 0xE0 /* DBC 1st byte range 2 start */ @@ -258,7 +165,7 @@ typedef struct _FILINFO { #define _DS2S 0x80 /* DBC 2nd byte range 2 start */ #define _DS2E 0xFC /* DBC 2nd byte range 2 end */ -#elif _CODE_PAGE == 936 /* CP936 (Simplified Chinese GBK) */ +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ #define _DF1S 0x81 #define _DF1E 0xFE #define _DS1S 0x40 @@ -266,7 +173,7 @@ typedef struct _FILINFO { #define _DS2S 0x80 #define _DS2E 0xFE -#elif _CODE_PAGE == 949 /* CP949 (Korean) */ +#elif _CODE_PAGE == 949 /* Korean */ #define _DF1S 0x81 #define _DF1E 0xFE #define _DS1S 0x41 @@ -276,7 +183,7 @@ typedef struct _FILINFO { #define _DS3S 0x81 #define _DS3E 0xFE -#elif _CODE_PAGE == 950 /* CP950 (Traditional Chinese Big5) */ +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ #define _DF1S 0x81 #define _DF1E 0xFE #define _DS1S 0x40 @@ -284,8 +191,158 @@ typedef struct _FILINFO { #define _DS2S 0xA1 #define _DS2E 0xFE -#else /* SBCS code pages */ +#elif _CODE_PAGE == 437 /* U.S. (OEM) */ #define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 720 /* Arabic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 737 /* Greek (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 775 /* Baltic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + +#elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 857 /* Turkish (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 862 /* Hebrew (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 866 /* Russian (OEM) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ + 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} + +#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1253 /* Greek (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ + 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} + +#elif _CODE_PAGE == 1254 /* Turkish (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} + +#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1256 /* Arabic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 1257 /* Baltic (Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} + +#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ + 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} + +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#define _DF1S 0 + +#else +#error Unknown code page #endif @@ -343,6 +400,125 @@ const PARTITION Drives[]; /* Logical drive# to physical location conversion ta +/* Definitions corresponds to multiple sector size */ + +#if _MAX_SS == 512 +#define SS(fs) 512U + +#elif _MAX_SS == 1024 || _MAX_SS == 2048 || _MAX_SS == 4096 +#define SS(fs) ((fs)->s_size) + +#else +#error Sector size must be 512, 1024, 2048 or 4096. + +#endif + + + +/* Type of file name on FatFs API */ + +#if _LFN_UNICODE && _USE_LFN +typedef WCHAR XCHAR; /* Unicode */ +#else +typedef char XCHAR; /* SBCS, DBCS */ +#endif + + + +/* File system object structure */ + +typedef struct _FATFS_ { + BYTE fs_type; /* FAT sub type */ + BYTE drive; /* Physical drive number */ + BYTE csize; /* Number of sectors per cluster */ + BYTE n_fats; /* Number of FAT copies */ + BYTE wflag; /* win[] dirty flag (1:must be written back) */ + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (0 on FAT32) */ +#if _FS_REENTRANT + _SYNC_t sobj; /* Identifier of sync object */ +#endif +#if _MAX_SS != 512 + WORD s_size; /* Sector size */ +#endif +#if !_FS_READONLY + BYTE fsi_flag; /* fsinfo dirty flag (1:must be written back) */ + DWORD last_clust; /* Last allocated cluster */ + DWORD free_clust; /* Number of free clusters */ + DWORD fsi_sector; /* fsinfo sector */ +#endif +#if _FS_RPATH + DWORD cdir; /* Current directory (0:root)*/ +#endif + DWORD sects_fat; /* Sectors per fat */ + DWORD max_clust; /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */ + DWORD fatbase; /* FAT start sector */ + DWORD dirbase; /* Root directory start sector (Cluster# on FAT32) */ + DWORD database; /* Data start sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS];/* Disk access window for Directory/FAT */ +} FATFS; + + + +/* Directory object structure */ + +typedef struct _DIR_ { + FATFS* fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + WORD index; /* Current read/write index number */ + DWORD sclust; /* Table start cluster (0:Static table) */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector */ + BYTE* dir; /* Pointer to the current SFN entry in the win[] */ + BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ +#if _USE_LFN + WCHAR* lfn; /* Pointer to the LFN working buffer */ + WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ +#endif +} DIR; + + + +/* File object structure */ + +typedef struct _FIL_ { + FATFS* fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + BYTE flag; /* File status flags */ + BYTE csect; /* Sector address in the cluster */ + DWORD fptr; /* File R/W pointer */ + DWORD fsize; /* File size */ + DWORD org_clust; /* File start cluster */ + DWORD curr_clust; /* Current cluster */ + DWORD dsect; /* Current data sector */ +#if !_FS_READONLY + DWORD dir_sect; /* Sector containing the directory entry */ + BYTE* dir_ptr; /* Ponter to the directory entry in the window */ +#endif +#if !_FS_TINY + BYTE buf[_MAX_SS];/* File R/W buffer */ +#endif +} FIL; + + + +/* File status structure */ + +typedef struct _FILINFO_ { + DWORD fsize; /* File size */ + WORD fdate; /* Last modified date */ + WORD ftime; /* Last modified time */ + BYTE fattrib; /* Attribute */ + char fname[13]; /* Short file name (8.3 format) */ +#if _USE_LFN + XCHAR* lfname; /* Pointer to the LFN buffer */ + int lfsize; /* Size of LFN buffer [chrs] */ +#endif +} FILINFO; + + + /* File function return code (FRESULT) */ typedef enum { @@ -370,24 +546,26 @@ typedef enum { /* FatFs module application interface */ FRESULT f_mount (BYTE, FATFS*); /* Mount/Unmount a logical drive */ -FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */ +FRESULT f_open (FIL*, const XCHAR*, BYTE); /* Open or create a file */ FRESULT f_read (FIL*, void*, UINT, UINT*); /* Read data from a file */ FRESULT f_write (FIL*, const void*, UINT, UINT*); /* Write data to a file */ FRESULT f_lseek (FIL*, DWORD); /* Move file pointer of a file object */ FRESULT f_close (FIL*); /* Close an open file object */ -FRESULT f_opendir (DIR*, const char*); /* Open an existing directory */ +FRESULT f_opendir (DIR*, const XCHAR*); /* Open an existing directory */ FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ -FRESULT f_stat (const char*, FILINFO*); /* Get file status */ -FRESULT f_getfree (const char*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ +FRESULT f_stat (const XCHAR*, FILINFO*); /* Get file status */ +FRESULT f_getfree (const XCHAR*, DWORD*, FATFS**); /* Get number of free clusters on the drive */ FRESULT f_truncate (FIL*); /* Truncate file */ FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ -FRESULT f_unlink (const char*); /* Delete an existing file or directory */ -FRESULT f_mkdir (const char*); /* Create a new directory */ -FRESULT f_chmod (const char*, BYTE, BYTE); /* Change attriburte of the file/dir */ -FRESULT f_utime (const char*, const FILINFO*); /* Change timestamp of the file/dir */ -FRESULT f_rename (const char*, const char*); /* Rename/Move a file or directory */ +FRESULT f_unlink (const XCHAR*); /* Delete an existing file or directory */ +FRESULT f_mkdir (const XCHAR*); /* Create a new directory */ +FRESULT f_chmod (const XCHAR*, BYTE, BYTE); /* Change attriburte of the file/dir */ +FRESULT f_utime (const XCHAR*, const FILINFO*); /* Change timestamp of the file/dir */ +FRESULT f_rename (const XCHAR*, const XCHAR*); /* Rename/Move a file or directory */ FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ FRESULT f_mkfs (BYTE, BYTE, WORD); /* Create a file system on the drive */ +FRESULT f_chdir (const XCHAR*); /* Change current directory */ +FRESULT f_chdrive (BYTE); /* Change current drive */ #if _USE_STRFUNC int f_putc (int, FIL*); /* Put a character to the file */ @@ -415,6 +593,7 @@ DWORD get_fattime (void); /* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20 /* Unicode - OEM code conversion */ #if _USE_LFN WCHAR ff_convert (WCHAR, UINT); +WCHAR ff_wtoupper (WCHAR); #endif /* Sync functions */ diff --git a/src/option/cc932.c b/src/option/cc932.c index 8f7cd89..097c6a0 100644 --- a/src/option/cc932.c +++ b/src/option/cc932.c @@ -8,7 +8,9 @@ #define _TINY_TABLE 0 -#if _USE_LFN && _CODE_PAGE == 932 +#if !_USE_LFN || _CODE_PAGE != 932 +#error This file is not needed in current configuration. +#endif static @@ -3778,7 +3780,19 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */ return c; } -#else -#error This file is not needed in current configuration. -#endif + + +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ +) +{ + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; + + + for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + + return tbl_lower[i] ? tbl_upper[i] : chr; +} diff --git a/src/option/cc936.c b/src/option/cc936.c index 4238d91..1a034a9 100644 --- a/src/option/cc936.c +++ b/src/option/cc936.c @@ -7,8 +7,9 @@ #include "../ff.h" -#if _USE_LFN && _CODE_PAGE == 936 - +#if !_USE_LFN || _CODE_PAGE != 936 +#error This file is not needed in current configuration. +#endif static const WCHAR uni2oem[] = { @@ -10954,7 +10955,19 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */ return c; } -#else -#error This file is not needed in current configuration. -#endif + + +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ +) +{ + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; + + + for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + + return tbl_lower[i] ? tbl_upper[i] : chr; +} diff --git a/src/option/cc949.c b/src/option/cc949.c index 8967985..2b1e793 100644 --- a/src/option/cc949.c +++ b/src/option/cc949.c @@ -7,7 +7,9 @@ #include "../ff.h" -#if _USE_LFN && _CODE_PAGE == 949 +#if !_USE_LFN || _CODE_PAGE != 949 +#error This file is not needed in current configuration. +#endif static @@ -8582,7 +8584,20 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */ return c; } -#else -#error This file is not needed in current configuration. -#endif + + + +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ +) +{ + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; + + + for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + + return tbl_lower[i] ? tbl_upper[i] : chr; +} diff --git a/src/option/cc950.c b/src/option/cc950.c index 8e61677..0d73695 100644 --- a/src/option/cc950.c +++ b/src/option/cc950.c @@ -7,7 +7,9 @@ #include "../ff.h" -#if _USE_LFN && _CODE_PAGE == 950 +#if !_USE_LFN || _CODE_PAGE != 950 +#error This file is not needed in current configuration. +#endif static @@ -6808,7 +6810,20 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */ return c; } -#else -#error This file is not needed in current configuration. -#endif + + + +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ +) +{ + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; + + + for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + + return tbl_lower[i] ? tbl_upper[i] : chr; +} diff --git a/src/option/ccsbcs.c b/src/option/ccsbcs.c index 84ea404..9a9eac1 100644 --- a/src/option/ccsbcs.c +++ b/src/option/ccsbcs.c @@ -1,13 +1,34 @@ /*------------------------------------------------------------------------*/ -/* Unicode - OEM code bidirectional converter (C)ChaN, 2009 */ -/* */ -/* SBCS code */ +/* Unicode - Local code bidirectional converter (C)ChaN, 2009 */ +/* (SBCS code pages) */ /*------------------------------------------------------------------------*/ +/* 437 U.S. (OEM) +/ 720 Arabic (OEM) +/ 1256 Arabic (Windows) +/ 737 Greek (OEM) +/ 1253 Greek (Windows) +/ 1250 Central Europe (Windows) +/ 775 Baltic (OEM) +/ 1257 Baltic (Windows) +/ 850 Multilingual Latin 1 (OEM) +/ 852 Latin 2 (OEM) +/ 1252 Latin 1 (Windows) +/ 855 Cyrillic (OEM) +/ 1251 Cyrillic (Windows) +/ 866 Russian (OEM) +/ 857 Turkish (OEM) +/ 1254 Turkish (Windows) +/ 858 Multilingual Latin 1 + Euro (OEM) +/ 862 Hebrew (OEM) +/ 1255 Hebrew (Windows) +/ 874 Thai (OEM, Windows) +/ 1258 Vietnam (OEM, Windows) +*/ #include "../ff.h" -#if _USE_LFN && _CODE_PAGE == 437 +#if _CODE_PAGE == 437 #define _TBLDEF 1 static const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */ @@ -271,6 +292,182 @@ const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */ 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 }; +#elif _CODE_PAGE == 1250 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0161, 0x203A, 0x015B, 0x0165, 0x017E, 0x017A, + 0x00A0, 0x02C7, 0x02D8, 0x0141, 0x00A4, 0x0104, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x015E, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x017B, + 0x00B0, 0x00B1, 0x02DB, 0x0142, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x0105, 0x015F, 0x00BB, 0x013D, 0x02DD, 0x013E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, + 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, + 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, + 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, + 0x0159, 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 +}; + +#elif _CODE_PAGE == 1251 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */ + 0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021, + 0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F, + 0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2111, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F, + 0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7, + 0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407, + 0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7, + 0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457, + 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, 0x042D, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, + 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, + 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F +}; + +#elif _CODE_PAGE == 1252 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x017E, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF +}; + +#elif _CODE_PAGE == 1253 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x0385, 0x0386, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x0000, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x00B5, 0x00B6, 0x00B7, + 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, + 0x03A8, 0x03A9, 0x03AA, 0x03AD, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, + 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, + 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 +}; + +#elif _CODE_PAGE == 1254 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0161, 0x203A, 0x0153, 0x0000, 0x0000, 0x0178, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, + 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, + 0x00D8, 0x00D9, 0x00DA, 0x00BD, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, + 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF +}; + +#elif _CODE_PAGE == 1255 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x02DC, 0x2122, 0x0000, 0x203A, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7, + 0x05B8, 0x05B9, 0x0000, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF, + 0x05C0, 0x05C1, 0x05C2, 0x05C3, 0x05F0, 0x05F1, 0x05F2, 0x05F3, + 0x05F4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 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, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 +}; + +#elif _CODE_PAGE == 1256 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021, + 0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688, + 0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x06A9, 0x2122, 0x0691, 0x203A, 0x0153, 0x200C, 0x200D, 0x06BA, + 0x00A0, 0x060C, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, + 0x00A8, 0x00A9, 0x06BE, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x061B, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x061F, + 0x06C1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00D7, + 0x0637, 0x0638, 0x0639, 0x063A, 0x0640, 0x0640, 0x0642, 0x0643, + 0x00E0, 0x0644, 0x00E2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00E7, + 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x0649, 0x064A, 0x00EE, 0x00EF, + 0x064B, 0x064C, 0x064D, 0x064E, 0x00F4, 0x064F, 0x0650, 0x00F7, + 0x0651, 0x00F9, 0x0652, 0x00FB, 0x00FC, 0x200E, 0x200F, 0x06D2 +} + +#elif _CODE_PAGE == 1257 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */ + 0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021, + 0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8, + 0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, + 0x0000, 0x2122, 0x0000, 0x203A, 0x0000, 0x00AF, 0x02DB, 0x0000, + 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x0000, 0x00A6, 0x00A7, + 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, + 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, + 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, + 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, + 0x0173, 0x014E, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x02D9 +}; + #elif _CODE_PAGE == 1258 #define _TBLDEF 1 static @@ -296,14 +493,16 @@ const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */ #endif -#if _TBLDEF +#if !_TBLDEF || !_USE_LFN +#error This file is not needed in current configuration +#endif -WCHAR ff_convert ( /* Converted code, 0 means conversion error */ + +WCHAR ff_convert ( /* Converted character, Returns zero on error */ WCHAR src, /* Character code to be converted */ UINT dir /* 0: Unicode to OEMCP, 1: OEMCP to Unicode */ ) { - const WCHAR *p; WCHAR c; @@ -325,8 +524,17 @@ WCHAR ff_convert ( /* Converted code, 0 means conversion error */ return c; } -#else -#error This file is not needed in current configuration -#endif +WCHAR ff_wtoupper ( /* Upper converted character */ + WCHAR chr /* Input character */ +) +{ + static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 }; + static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 }; + int i; + + for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ; + + return tbl_lower[i] ? tbl_upper[i] : chr; +}