From 9a43e8b517573bc0a61679f559d7339ea77b60bd Mon Sep 17 00:00:00 2001 From: savelij13 Date: Thu, 11 Sep 2025 08:56:57 +0300 Subject: [PATCH] fatfs v0.03 Sep 22, 2006: - Added f_rename(). - Changed option _FS_MINIMUM to _FS_MINIMIZE. --- doc/00index_e.html | 30 +-- doc/00index_j.html | 24 +-- doc/en/chmod.html | 16 +- doc/en/close.html | 2 +- doc/en/getfree.html | 6 +- doc/en/lseek.html | 8 +- doc/en/mkdir.html | 16 +- doc/en/mountdrv.html | 9 +- doc/en/open.html | 18 +- doc/en/opendir.html | 10 +- doc/en/read.html | 4 +- doc/en/readdir.html | 4 +- doc/en/rename.html | 83 ++++++++ doc/en/stat.html | 10 +- doc/en/sync.html | 4 +- doc/en/unlink.html | 14 +- doc/en/write.html | 4 +- doc/ja/chmod.html | 8 +- doc/ja/getfree.html | 2 +- doc/ja/mkdir.html | 12 +- doc/ja/mountdrv.html | 6 +- doc/ja/open.html | 12 +- doc/ja/opendir.html | 6 +- doc/ja/readdir.html | 2 +- doc/ja/rename.html | 83 ++++++++ doc/ja/stat.html | 6 +- doc/ja/unlink.html | 8 +- src/00readme.txt | 69 ++++--- src/ff.c | 429 ++++++++++++++++++++++------------------ src/ff.h | 80 ++++---- src/integer.h | 6 + src/tff.c | 456 ++++++++++++++++++++++++------------------- src/tff.h | 95 ++++----- 33 files changed, 926 insertions(+), 616 deletions(-) create mode 100644 doc/en/rename.html create mode 100644 doc/ja/rename.html diff --git a/doc/00index_e.html b/doc/00index_e.html index ca094df..76d91da 100644 --- a/doc/00index_e.html +++ b/doc/00index_e.html @@ -3,8 +3,6 @@ - - ELM - Generic FAT Files System Module @@ -16,11 +14,12 @@
-

FatFs module is an experimental project to implement FAT file system to small embdded systems. The FatFs module is written in compliance with ANSI C, therefore it is independent of hardware architecture. It can be incorporated into most small microcontrollers, such as PIC, AVR, H8, Z80 and etc..., without any change. I created two modules in different configurations in consideration of various use. To use the FatFs module, low level disk I/O functions for each media must be provided by user.

+

FatFs module is an experimental project to implement FAT file system to small embdded systems. The FatFs module is written in compliance with ANSI C, therefore it is independent of hardware architecture. It can be incorporated into most small microcontrollers, such as 8051, PIC, AVR, H8, Z80 and etc..., without any change. I created two modules in different configurations in consideration of various use. To use the FatFs module, low level disk I/O functions for each media must be provided by user.

Features of FatFs Module

- - - - + + + +
Tiny-FatFs
SectionStd cfg.Min cfg.
Program (R/W cfg.)68685208
Program (R/O cfg.)38043136
Work Area (static)2
Work Area (dynamic)538 + 24 * <files>
Program (R/W cfg.)71124836
Program (R/O cfg.)35382774
Static Work Area2
Dynamic Work Area538 + 24 * <files>
@@ -79,6 +79,7 @@
  • f_mkdir - Create a Directory
  • f_unlink - Remove a File or Directory
  • f_chmod - Change Attribute
  • +
  • f_rename - Rename/Move a File or Directory
  • f_mountdrv - Force Initialized FatFs Module
  • @@ -86,7 +87,7 @@

    Disk I/O Interface

    -

    FatFs/Tiny-FatFs module requires following functions to lower layer to read/write physical disk and to get current time.

    +

    Since the FatFs/Tiny-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.

    - - - - + + + +
    Tiny-FatFs
    セクション標準最小
    Program (R/W cfg.)68685208
    Program (R/O cfg.)38043136
    Work Area (static)2
    Work Area (dynamic)538 + 24 * <files>
    プログラム(R/W構成)71124836
    プログラム(R/O構成)35382774
    静的ワークエリア2
    動的ワークエリア538 + 24 * <files>
    @@ -78,6 +78,7 @@
  • f_mkdir - ディレクトリの作成
  • f_unlink - ファイルまたはディレクトリの削除
  • f_chmod - ファイルまたはディレクトリ属性の変更
  • +
  • f_rename - ファイルまたはディレクトリの名前変更・移動
  • f_mountdrv - ファイル・システムの明示的初期化
  • @@ -101,9 +102,10 @@

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


    diff --git a/doc/en/chmod.html b/doc/en/chmod.html index a1e5f24..5c76ba6 100644 --- a/doc/en/chmod.html +++ b/doc/en/chmod.html @@ -48,22 +48,22 @@ FRESULT f_chmod (
    FR_OK (0)
    The function succeeded.
    -
    FR_NOFILE
    +
    FR_NO_FILE
    Could not find the file.
    -
    FR_NOPATH
    +
    FR_NO_PATH
    Could not find the path.
    FR_INVALID_NAME
    The file name is invalid.
    FR_NOT_READY
    The disk drive cannot work due to no medium in the drive or any other reason.
    FR_WRITE_PROTECTED
    -
    The medium is in write protected.
    +
    The medium is write protected.
    FR_RW_ERROR
    Any error occured in low level disk I/O.
    FR_INCORRECT_DISK_CHANGE
    -
    Incorrect disk removal, such as a medium change during any file is opend, has been occured.
    +
    Incorrect disk removal/change has occured.
    FR_NOT_ENABLED
    -
    FatFs module has not been enabled.
    +
    FatFs module is not enabled.
    FR_NO_FILESYSTEM
    There is no valid FAT partition on the disk.
    @@ -72,15 +72,15 @@ FRESULT f_chmod (

    Description

    -

    The f_chmod changes the attribute of a file or directory. This function is not supported in read-only and minimum configuration.

    +

    The f_chmod changes the attribute of a file or directory. This function is not supported in read-only configuration and minimization level of >=1.

    -

    Sample Code

    +

    Example

         // Set read-only flag, clear archive flag and others are not changed.
    -    f_chmod("/file.txt", AR_RDO, AR_RDO | AR_ARC);
    +    f_chmod("file.txt", AR_RDO, AR_RDO | AR_ARC);
     
    diff --git a/doc/en/close.html b/doc/en/close.html index 60888d9..ac78e64 100644 --- a/doc/en/close.html +++ b/doc/en/close.html @@ -37,7 +37,7 @@ FRESULT f_close (
    FR_RW_ERROR
    Any error occured in low level disk I/O.
    FR_INCORRECT_DISK_CHANGE
    -
    Incorrect disk removal, such as a medium change during any file is opend, has been occured.
    +
    Incorrect disk removal/change occured.
    FR_NOT_ENABLED
    FatFs module is not enabled.
    diff --git a/doc/en/getfree.html b/doc/en/getfree.html index 0daa9b1..86a516b 100644 --- a/doc/en/getfree.html +++ b/doc/en/getfree.html @@ -39,9 +39,9 @@ FRESULT f_getfree (
    FR_RW_ERROR
    Any error occured in low level disk I/O.
    FR_INCORRECT_DISK_CHANGE
    -
    Incorrect disk removal, such as a medium change during any file is opend, has been occured.
    +
    Incorrect disk removal/change has occured.
    FR_NOT_ENABLED
    -
    FatFs module has not been enabled.
    +
    FatFs module is not enabled.
    FR_NO_FILESYSTEM
    There is no valid FAT partition on the disk.
    @@ -50,7 +50,7 @@ FRESULT f_getfree (

    Descriptions

    -

    The f_getfree gets number of free clusters on the drive. The FatFs.sects_clust is indicating number of sectors per cluster, so that the free space in unit of byte can be calcurated with this. This function is not supported in minimum configuration.

    +

    The f_getfree gets number of free clusters on the drive. The FatFs.sects_clust is indicating number of sectors per cluster, so that the free space in unit of byte can be calcurated with this. This function is not supported in read-only configuration and minimization level of >= 1.

    diff --git a/doc/en/lseek.html b/doc/en/lseek.html index 26134cb..034dded 100644 --- a/doc/en/lseek.html +++ b/doc/en/lseek.html @@ -42,7 +42,7 @@ FRESULT f_lseek (
    FR_INCORRECT_DISK_CHANGE
    Incorrect disk removal, such as a medium change during any file is opend, has been occured.
    FR_NOT_ENABLED
    -
    FatFs module has not been enabled.
    +
    FatFs module is not enabled.
    @@ -54,9 +54,9 @@ FRESULT f_lseek (
    -

    Sample Code

    +

    Example

    -    // Move to offset of 5000 from top of file.
    +    // Move to offset of 5000 from top of the file.
         res = f_lseek(&file, 5000);
     
         // Forward 3000 bytes
    @@ -65,7 +65,7 @@ FRESULT f_lseek (
         // Rewind 2000 bytes
         res = f_lseek(&file, file.fptr - 2000);
     
    -    // Move to end of file
    +    // Move to end of the file
         res = f_lseek(&file, 0xFFFFFFFF);
     
    diff --git a/doc/en/mkdir.html b/doc/en/mkdir.html index d284800..a6181c5 100644 --- a/doc/en/mkdir.html +++ b/doc/en/mkdir.html @@ -34,7 +34,7 @@ FRESULT f_mkdir (
    FR_OK (0)
    The function succeeded.
    -
    FR_NOPATH
    +
    FR_NO_PATH
    Could not find the path.
    FR_INVALID_NAME
    The path name is invalid.
    @@ -47,9 +47,9 @@ FRESULT f_mkdir (
    FR_RW_ERROR
    Any error occured in low level disk I/O.
    FR_INCORRECT_DISK_CHANGE
    -
    Incorrect disk removal, such as a medium change during any file is opend, has been occured.
    +
    Incorrect disk removal/change has occured.
    FR_NOT_ENABLED
    -
    FatFs module has not been enabled.
    +
    FatFs module is not enabled.
    FR_NO_FILESYSTEM
    There is no valid FAT partition on the disk.
    @@ -58,20 +58,20 @@ FRESULT f_mkdir (

    Description

    -

    The f_mkdir creates an empty directory. This function is not supported in read-only and minimum configuration.

    +

    The f_mkdir creates an empty directory. This function is not supported in read-only configuration and minimization level of >= 1.

    -

    Sample Code

    +

    Example

    -    res = f_mkdir("/sub1");
    +    res = f_mkdir("sub1");
         if (res) die(res);
    -    res = f_mkdir("/sub1/sub2");
    +    res = f_mkdir("sub1/sub2");
         if (res) die(res);
    -    res = f_mkdir("/sub1/sub2/sub3");
    +    res = f_mkdir("sub1/sub2/sub3");
         if (res) die(res);
     
    diff --git a/doc/en/mountdrv.html b/doc/en/mountdrv.html index b867c44..61ae042 100644 --- a/doc/en/mountdrv.html +++ b/doc/en/mountdrv.html @@ -12,9 +12,9 @@

    f_mountdrv

    -

    The f_mountdrv forces mounted the partition.

    +

    The f_mountdrv forces the partition mounted.

    -FRESULT f_mountdrv ();
    +FRESULT f_mountdrv (void);
     
    @@ -28,7 +28,7 @@ FRESULT f_mountdrv ();
    FR_RW_ERROR
    Any error occured in low level disk I/O.
    FR_NOT_ENABLED
    -
    FatFs module has not been enabled.
    +
    FatFs module is not enabled.
    FR_NO_FILESYSTEM
    There is no valid FAT partition on the disk.
    @@ -37,7 +37,8 @@ FRESULT f_mountdrv ();

    Description

    -

    The f_mountdrv mounts a partition (initializes FATFS structure) and put it that can handle all file functions. This function should not be used except for recover FR_INCORRECT_DISK_CHANGE error because the file system is mounted(initialized) automatically in accordance with the necessity when any file function is called. To terminate use of the FatFs module, close all files and then the FATFS structure can be discarded. In this function, following process is executed.


    +

    The f_mountdrv forces the partition mounted (initializes FATFS structure). This function should not be used except for recover FR_INCORRECT_DISK_CHANGE error. The file system is initialized automatically in accordance with the necessity when any file function is called.

    +

    To terminate use of the FatFs module, close all files and then the FATFS structure can be discarded. In this function, following process is executed.


    @@ -48,9 +48,9 @@ FRESULT f_chmod (
    FR_OK (0)
    正常終了。
    -
    FR_NOFILE
    +
    FR_NO_FILE
    ファイルが見つからない。
    -
    FR_NOPATH
    +
    FR_NO_PATH
    パスが見つからない。
    FR_INVALID_NAME
    パス名が不正。
    @@ -72,7 +72,7 @@ FRESULT f_chmod (

    解説

    -

    ファイルまたはディレクトリの属性を変更します。リードオンリー構成およびミニマム構成ではこの関数はサポートされません。

    +

    ファイルまたはディレクトリの属性を変更します。リードオンリー構成および_FS_MINIMIZE >= 1ではこの関数はサポートされません。

    diff --git a/doc/ja/getfree.html b/doc/ja/getfree.html index 09504af..f7a99f4 100644 --- a/doc/ja/getfree.html +++ b/doc/ja/getfree.html @@ -50,7 +50,7 @@ FRESULT f_getfree (

    解説

    -

    ファイルシステム上の空きクラスタ数を取得します。FatFs.sects_clust がクラスタあたりのセクタ数を示しているので、これを元に実際の空きサイズが計算できます。ミニマム構成ではこの関数はサポートされません。

    +

    ファイルシステム上の空きクラスタ数を取得します。FatFs.sects_clust がクラスタあたりのセクタ数を示しているので、これを元に実際の空きサイズが計算できます。リードオンリー構成および_FS_MINIMIZE >= 1ではこの関数はサポートされません。

    diff --git a/doc/ja/mkdir.html b/doc/ja/mkdir.html index 4a8e14f..c8c9040 100644 --- a/doc/ja/mkdir.html +++ b/doc/ja/mkdir.html @@ -24,7 +24,7 @@ FRESULT f_mkdir (

    パラメータ

    DirName
    -
    作成するディレクトリのフルパス名が入った'\0'で終わる文字列へのポインタを指定します。ディレクトリセパレータには'/'を使用します。FatFsモジュールにはカレントディレクトリの概念がないので、パスはルートディレクトリから辿る絶対パスとなります。文字列先頭のスペースはスキップされます。パス先頭の'/'はあってもなくてもかまいません。ミニマム構成ではこの関数はサポートされません。
    +
    作成するディレクトリのフルパス名が入った'\0'で終わる文字列へのポインタを指定します。ディレクトリセパレータには'/'を使用します。FatFsモジュールにはカレントディレクトリの概念がないので、パスはルートディレクトリから辿る絶対パスとなります。文字列先頭のスペースはスキップされます。パス先頭の'/'はあってもなくてもかまいません。リードオンリー構成および _FS_MINIMIZE >= 1 ではこの関数はサポートされません。
    @@ -34,7 +34,7 @@ FRESULT f_mkdir (
    FR_OK (0)
    正常終了。
    -
    FR_NOPATH
    +
    FR_NO_PATH
    パスが見つからない。
    FR_INVALID_NAME
    パス名が不正。
    @@ -58,7 +58,7 @@ FRESULT f_mkdir (

    解説

    -

    空のディレクトリを作成します。リードオンリー構成ではこの関数はサポートされません。

    +

    空のディレクトリを作成します。リードオンリー構成および_FS_MINIMIZE >= 1ではこの関数はサポートされません。

    @@ -67,11 +67,11 @@ FRESULT f_mkdir (

    使用例

    -    res = f_mkdir("/sub1");
    +    res = f_mkdir("sub1");
         if (res) die(res);
    -    res = f_mkdir("/sub1/sub2");
    +    res = f_mkdir("sub1/sub2");
         if (res) die(res);
    -    res = f_mkdir("/sub1/sub2/sub3");
    +    res = f_mkdir("sub1/sub2/sub3");
         if (res) die(res);
     
    diff --git a/doc/ja/mountdrv.html b/doc/ja/mountdrv.html index d4efcf8..7787700 100644 --- a/doc/ja/mountdrv.html +++ b/doc/ja/mountdrv.html @@ -14,7 +14,7 @@

    f_mountdrv

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

    -FRESULT f_mountdrv ();
    +FRESULT f_mountdrv (void);
     
    @@ -37,8 +37,8 @@ FRESULT f_mountdrv ();

    解説

    -

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

    -

    FatFsモジュールの使用を終了するには、全てのファイルを閉じたあとグローバル変数FatFsをクリアします。その後、ワークエリアは解放できます。f_mountdrv関数内では次の処理が行われます。

    +

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

    +

    FatFsモジュールの使用を終了するには、全てのファイルを閉じたあとグローバル変数FatFsをクリアします。その後、FatFsモジュールのワークエリアは解放できます。f_mountdrv関数内では次の処理が行われます。


    • 下位レイヤ(ディスクI/Oモジュール)の初期化。
    • diff --git a/doc/ja/open.html b/doc/ja/open.html index 1545b58..7697876 100644 --- a/doc/ja/open.html +++ b/doc/ja/open.html @@ -49,9 +49,9 @@ FRESULT f_open (
      FR_OK (0)
      正常終了。以降、FileObject構造体を使ってこのファイルを操作できます。ファイルを閉じるときは、f_close()を使用します。
      -
      FR_NOFILE
      +
      FR_NO_FILE
      ファイルが見つからない。
      -
      FR_NOPATH
      +
      FR_NO_PATH
      パスが見つからない。
      FR_INVALID_NAME
      ファイル名が不正。
      @@ -97,19 +97,19 @@ void main () FatFs = &fs; // ソース・ファイルを開く - res = f_open(&fsrc, "/srcfile.dat", FA_OPEN_EXISTING | FA_READ); + res = f_open(&fsrc, "srcfile.dat", FA_OPEN_EXISTING | FA_READ); if (res) die(res); // デスティネーション・ファイルを作成する - res = f_open(&fdst, "/dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE); + res = f_open(&fdst, "dstfile.dat", FA_CREATE_ALWAYS | FA_WRITE); if (res) die(res); // ソースからデスティネーションにコピーする for (;;) { res = f_read(&fsrc, buffer, sizeof(buffer), &br); - if (res || br == 0) break; + if (res || br == 0) break; // error or eof res = f_write(&fdst, buffer, br, &bw); - if (res || bw < br) break; + if (res || bw < br) break; // error or disk full } // 全てのファイルを閉じる diff --git a/doc/ja/opendir.html b/doc/ja/opendir.html index c98fdc8..c462d69 100644 --- a/doc/ja/opendir.html +++ b/doc/ja/opendir.html @@ -37,7 +37,9 @@ FRESULT f_opendir (
      FR_OK (0)
      正常終了。
      -
      FR_NOPATH
      +
      FR_NO_FILE
      +
      ディレクトリが見つからない。
      +
      FR_NO_PATH
      パスが見つからない。
      FR_INVALID_NAME
      パス名が不正。
      @@ -57,7 +59,7 @@ FRESULT f_opendir (

      解説

      -

      ディレクトリをオープンします。正常終了したら、DirObject構造体を使ってこのディレクトリの項目を順次読み出せます。使用後の処理は必要ありません。DirObject構造体は任意の時点で破棄できます。ミニマム構成ではこの関数はサポートされません。

      +

      ディレクトリをオープンします。正常終了したら、DirObject構造体を使ってこのディレクトリの項目を順次読み出せます。使用後の処理は必要ありません。DirObject構造体は任意の時点で破棄できます。_FS_MINIMIZE == 2ではこの関数はサポートされません。

      diff --git a/doc/ja/readdir.html b/doc/ja/readdir.html index fdc2d3f..0022bab 100644 --- a/doc/ja/readdir.html +++ b/doc/ja/readdir.html @@ -49,7 +49,7 @@ FRESULT f_readdir (

      解説

      -

      ディレクトリ項目を順次読み出します。この関数を繰り返し実行することによりディレクトリの全ての項目を読み出すことができます。全ての項目を読み出し、読み出す項目がもう無いときは、f_name[]メンバにヌル文字列が返されます。得られるファイル情報の詳細については FILINFO構造体を参照してください。ミニマム構成ではこの関数はサポートされません。

      +

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

      diff --git a/doc/ja/rename.html b/doc/ja/rename.html new file mode 100644 index 0000000..82837ce --- /dev/null +++ b/doc/ja/rename.html @@ -0,0 +1,83 @@ + + + + + + + +FatFs - f_rename + + + + +
      +

      f_chmod

      +

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

      +
      +FRESULT f_rename (
      +  const char* OldName, // 古いファイルまたはディレクトリの文字列へのポインタ
      +  const char* NewName  // 新しいファイルまたはディレクトリの文字列へのポインタ
      +);
      +
      +
      + +
      +

      パラメータ

      +
      +
      OldName
      +
      変更対象のファイルまたはディレクトリのフルパス名の入った'\0'で終わる文字列へのポインタを指定します。
      +
      NewName
      +
      新しいファイルまたはディレクトリのフルパス名の入った'\0'で終わる文字列へのポインタを指定します。既に存在するものと同じ名前は使えません。
      +
      +
      + + +
      +

      戻り値

      +
      +
      FR_OK (0)
      +
      正常終了。
      +
      FR_NO_FILE
      +
      ファイルが見つからない。
      +
      FR_NO_PATH
      +
      パスが見つからない。
      +
      FR_INVALID_NAME
      +
      パス名が不正。
      +
      FR_DENIED
      +
      新しい名前が作れない。
      +
      FR_NOT_READY
      +
      メディアがセットされていないなど、ディスクドライブが動作不能状態。
      +
      FR_WRITE_PROTECTED
      +
      メディアが書き込み禁止状態。
      +
      FR_RW_ERROR
      +
      ディスクアクセスでエラーが発生した。
      +
      FR_INCORRECT_DISK_CHANGE
      +
      不正なメディアの取り外しがあった。ファイルを開いたままのメディア交換など。
      +
      FR_NOT_ENABLED
      +
      FatFsモジュールが停止状態。
      +
      FR_NO_FILESYSTEM
      +
      ディスク上に有効なFATパーテーションが見つからない。
      +
      +
      + + +
      +

      解説

      +

      ファイルまたはディレクトリの名前を変更します。別のディレクトリへの移動も可能です。リードオンリー構成および_FS_MINIMIZE >= 1ではこの関数はサポートされません。

      +
      + + +
      +

      使用例

      +
      +    // 名前を変更する
      +    f_rename("oldname.txt", "newname.txt");
      +
      +    // 名前の変更と同時に別のディレクトリへ移動する
      +    f_rename("oldname.txt", "dir1/newname.txt");
      +
      +
      + +

      戻る

      + + diff --git a/doc/ja/stat.html b/doc/ja/stat.html index 54fc0c7..82e16f9 100644 --- a/doc/ja/stat.html +++ b/doc/ja/stat.html @@ -37,7 +37,9 @@ FRESULT f_stat (
      FR_OK (0)
      正常終了。
      -
      FR_NOPATH
      +
      FR_NO_FILE
      +
      ファイルまたはディレクトリが見つからない。
      +
      FR_NO_PATH
      パスが見つからない。
      FR_INVALID_NAME
      パス名が不正。
      @@ -57,7 +59,7 @@ FRESULT f_stat (

      解説

      -

      ファイルまたはディレクトリに関する情報を得ます。得られるファイル情報の詳細については FILINFO構造体を参照してください。ミニマム構成ではこの関数はサポートされません。

      +

      ファイルまたはディレクトリに関する情報を得ます。得られるファイル情報の詳細については FILINFO構造体を参照してください。_FS_MINIMIZE >= 1ではこの関数はサポートされません。

      diff --git a/doc/ja/unlink.html b/doc/ja/unlink.html index 00dff69..3148622 100644 --- a/doc/ja/unlink.html +++ b/doc/ja/unlink.html @@ -24,7 +24,7 @@ FRESULT f_unlink (

      パラメータ

      FileName
      -
      削除対象のファイルまたはディレクトリ名の入った'\0'で終わる文字列へのポインタを指定します。リードオンリー構成およびミニマム構成ではこの関数はサポートされません。
      +
      削除対象のファイルまたはディレクトリ名の入った'\0'で終わる文字列へのポインタを指定します。リードオンリー構成および _FS_MINIMIZE >= 1 ではこの関数はサポートされません。
    @@ -34,9 +34,9 @@ FRESULT f_unlink (
    FR_OK (0)
    正常終了。
    -
    FR_NOFILE
    +
    FR_NO_FILE
    ファイルが見つからない。
    -
    FR_NOPATH
    +
    FR_NO_PATH
    パスが見つからない。
    FR_INVALID_NAME
    パス名が不正。
    @@ -60,7 +60,7 @@ FRESULT f_unlink (

    解説

    -

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

    +

    ファイルまたはディレクトリを削除します。_FS_MINIMIZE >= 1ではこの関数はサポートされません。

    戻る

    diff --git a/src/00readme.txt b/src/00readme.txt index 40b5821..6f44aca 100644 --- a/src/00readme.txt +++ b/src/00readme.txt @@ -1,14 +1,14 @@ -FatFs/Tiny-FatFs Module Source Files R0.02a (C)ChaN, 2006 +FatFs/Tiny-FatFs Module Source Files R0.03 (C)ChaN, 2006 -Files +FILES ff.h Common include file for FatFs and application module. ff.c FatFs module. tff.h Common include file for Tiny-FatFs and application module. tff.c Tiny-FatFs module. diskio.h Common include file for (Tiny-)FatFs and disk I/O module. - integer.h Alternative type definitions for unsigned integers. + integer.h Alternative type definitions for integer variables. Low level disk I/O module is not included in this archive because the FatFs/Tiny-FatFs module is only a generic file system layer and not depend @@ -17,74 +17,83 @@ Files -Configuration Options +CONFIGURATION OPTIONS There are several configuration options for various envilonment and - requirement. The configuration options are in include files, ff.h and - tff.h. + requirement. The configuration options are defined in header files, ff.h + and tff.h. _BYTE_ACC This is the most impotant option that depends on the processor architecture. When your microcontroller corresponds to either or both of following terms, - the _BYTE_ACC must be defined. + the _BYTE_ACC must be defined to force FatFs to access FAT structure in + byte-by-byte. If not, this can be undefined to improve code size. This is + UNDEFINED in default. - Muti-byte integers (short, long) are stored in Big-Endian. - - An address unaligned word access causes an address error or any incorrect - behavior. + - Address miss-aligned memory access causes an address error or any + incorrect behavior. _FS_READONLY When application program does not require any write function, _FS_READONLY - can be defined to eliminate writing code to reduce module size. + can be defined to eliminate writing code to reduce module size. This is + UNDEFINED in default. - _FS_MINIMUM + _FS_MINIMIZE - When application program requires only file read/write function, _FS_MINIMUM - can be defined to eliminate other functions to reduce module size. + When application program requires only file read/write function, _FS_MINIMIZE + can be defined to eliminate some functions to reduce the module size. The + default value is 0 (full function). _USE_SJIS When _USE_SJIS is defined, Shift-JIS code set can be used as a file name, - otherwire second byte of double-byte characters will be collapted. + otherwire second byte of double-byte characters will be collapted. This is + DEFINED in default. - Following list shows which function is removed by configuratin options. + Following table shows which function is removed by configuratin options. - _FS_MINIMUM _FS_READONLY + _FS_MINIMIZE _FS_MINIMIZE _FS_READONLY + (1) (2) f_open - f_read - f_write x f_close - f_sync x + f_read f_lseek - f_opendir x - f_readdir x - f_stat x - f_getfree x - f_unlink x x - f_mkdir x x - f_chmod x x + f_write x + f_sync x + f_opendir x + f_readdir x + f_stat x x + f_getfree x x x + f_unlink x x x + f_mkdir x x x + f_chmod x x x + f_rename x x x f_mountdrv -Agreements +AGREEMENTS The FatFs/Tiny-FatFs module is a free software and there is no warranty. The FatFs/Tiny-FatFs module is opened for education, reserch and development. - You can use, modify and republish it for personal, non-profit or profit use - without any limitation under your responsibility. + You can use, modify and/or republish it for personal, non-profit or profit + use without any restriction under your responsibility. -Revision History +REVISION HISTORY Feb 26, 2006 R0.00 Prototype Apr 29, 2006 R0.01 First stable version Jun 01, 2006 R0.02 Added FAT12. Removed unbuffered mode. Fixed a problem on small (<32M) patition. Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM. + Sep 22, 2006 R0.03 Added f_rename(). + Changed option _FS_MINIMUM to _FS_MINIMIZE. diff --git a/src/ff.c b/src/ff.c index 3522a1c..f320f14 100644 --- a/src/ff.c +++ b/src/ff.c @@ -1,21 +1,23 @@ /*--------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.02a (C)ChaN, 2006 +/ FatFs - FAT file system module R0.03 (C)ChaN, 2006 /---------------------------------------------------------------------------/ / FatFs module is an experimenal project to implement FAT file system to -/ cheap microcontrollers. This is a freeware and is opened for education, -/ research and development. You can use, modify and republish it for -/ non-profit or profit use without any limitation under your responsibility. +/ cheap microcontrollers. This is a free software and is opened for education, +/ research and development. You can use, modify and/or republish it for +/ non-profit or profit use without any restriction under your responsibility. /---------------------------------------------------------------------------/ / Feb 26, 2006 R0.00 Prototype. / Apr 29, 2006 R0.01 First stable version. / Jun 01, 2006 R0.02 Added FAT12. Removed unbuffered mode. / Fixed a problem on small (<32M) patition. / Jun 10, 2006 R0.02a Added a configuration option (_FS_MINIMUM). +/ Sep 22, 2006 R0.03 Added f_rename(). +/ Changed option _FS_MINIMUM to _FS_MINIMIZE. /---------------------------------------------------------------------------*/ #include #include "ff.h" /* FatFs declarations */ -#include "diskio.h" /* Include file for user provided functions */ +#include "diskio.h" /* Include file for user provided disk functions */ FATFS *FatFs; /* Pointer to the file system object */ @@ -95,7 +97,7 @@ DWORD get_cluster ( return LD_DWORD(&(fs->win[((WORD)clust * 4) % 512])); } } - return 1; /* Return with 1 means function failed */ + return 1; /* There is no cluster information, or an error occured */ } @@ -123,7 +125,8 @@ BOOL put_cluster ( if (!move_window(fatsect + bc / 512)) return FALSE; p = &fs->win[bc % 512]; *p = (clust & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; - fs->winflag = 1; bc++; + bc++; + fs->winflag = 1; if (!move_window(fatsect + bc / 512)) return FALSE; p = &fs->win[bc % 512]; *p = (clust & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); @@ -161,9 +164,11 @@ BOOL remove_chain ( DWORD nxt; - while ((nxt = get_cluster(clust)) >= 2) { - if (!put_cluster(clust, 0)) return FALSE; - clust = nxt; + if (clust) { + while ((nxt = get_cluster(clust)) >= 2) { + if (!put_cluster(clust, 0)) return FALSE; + clust = nxt; + } } return TRUE; } @@ -298,11 +303,11 @@ BOOL next_dir_entry ( /*--------------------------------------*/ /* Get File Status from Directory Entry */ -#ifndef _FS_MINIMUM +#if _FS_MINIMIZE <= 1 static void get_fileinfo ( - FILINFO *finfo, /* Ptr to Store the File Information */ - const BYTE *dir /* Ptr to the Directory Entry */ + FILINFO *finfo, /* Ptr to store the file information */ + const BYTE *dir /* Ptr to the directory entry */ ) { BYTE n, c, a; @@ -334,7 +339,7 @@ void get_fileinfo ( finfo->fdate = LD_WORD(dir+24); /* Date */ finfo->ftime = LD_WORD(dir+22); /* Time */ } -#endif /* _FS_MINIMUM */ +#endif /* _FS_MINIMIZE <= 1 */ @@ -524,7 +529,7 @@ FRESULT check_mounted () if (fs->files) /* Drive was uninitialized with any file left opend */ return FR_INCORRECT_DISK_CHANGE; else - return f_mountdrv();; /* Initialize file system and return resulut */ + return f_mountdrv(); /* Initialize file system and return resulut */ } else { /* The drive has been initialized */ if (!fs->fs_type) /* But the file system has not been initialized */ return f_mountdrv(); /* Initialize file system and return resulut */ @@ -544,7 +549,7 @@ FRESULT check_mounted () /*----------------------------------------------------------*/ /* Load File System Information and Initialize FatFs Module */ -FRESULT f_mountdrv () +FRESULT f_mountdrv (void) { BYTE fat; DWORD sect, fatend, maxsect; @@ -596,60 +601,12 @@ FRESULT f_mountdrv () -/*-----------------------------*/ -/* Get Number of Free Clusters */ - -FRESULT f_getfree ( - DWORD *nclust /* Pointer to the double word to return number of free clusters */ -) -{ - DWORD n, clust, sect; - BYTE fat, f, *p; - FRESULT res; - FATFS *fs = FatFs; - - - if ((res = check_mounted()) != FR_OK) return res; - - /* Count number of free clusters */ - fat = fs->fs_type; - n = 0; - if (fat == FS_FAT12) { - clust = 2; - do { - if ((WORD)get_cluster(clust) == 0) n++; - } while (++clust < fs->max_clust); - } else { - clust = fs->max_clust; - sect = fs->fatbase; - f = 0; p = 0; - do { - if (!f) { - if (!move_window(sect++)) return FR_RW_ERROR; - p = fs->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 (--clust); - } - - *nclust = n; - return FR_OK; -} - - - /*-----------------------*/ /* Open or Create a File */ FRESULT f_open ( FIL *fp, /* Pointer to the buffer of new file object to create */ - const char *path, /* Pointer to the file path */ + const char *path, /* Pointer to the file name */ BYTE mode /* Access mode and file open mode flags */ ) { @@ -662,7 +619,7 @@ FRESULT f_open ( if ((res = check_mounted()) != FR_OK) return res; #ifndef _FS_READONLY - if ((mode & (FA_WRITE|FA_CREATE_ALWAYS)) && (disk_status() & STA_PROTECT)) + if ((mode & (FA_WRITE|FA_CREATE_ALWAYS|FA_OPEN_ALWAYS)) && (disk_status() & STA_PROTECT)) return FR_WRITE_PROTECTED; #endif @@ -680,7 +637,7 @@ FRESULT f_open ( memcpy(dir, fn, 8+3); /* Initialize the new entry */ *(dir+12) = fn[11]; memset(dir+13, 0, 32-13); - } else { /* File already exists */ + } else { /* Any object is already existing */ if ((dir == NULL) || (*(dir+11) & (AM_RDO|AM_DIR))) /* Could not overwrite (R/O or DIR) */ return FR_DENIED; if (mode & FA_CREATE_ALWAYS) { /* Resize it to zero */ @@ -716,7 +673,7 @@ FRESULT f_open ( fp->flag = mode & FA_READ; #else fp->flag = mode & (FA_WRITE|FA_READ); - fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ + fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ fp->dir_ptr = dir; #endif fp->org_clust = ((DWORD)LD_WORD(dir+20) << 16) | LD_WORD(dir+26); /* File start cluster */ @@ -751,19 +708,19 @@ FRESULT f_read ( if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */ if (!(fp->flag & FA_READ)) return FR_DENIED; /* Check access mode */ ln = fp->fsize - fp->fptr; - if (btr > ln) btr = ln; /* Truncate read count by number of bytes left */ + if (btr > ln) btr = (WORD)ln; /* Truncate read count by number of bytes left */ for ( ; btr; /* Repeat until all data transferred */ rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { if ((fp->fptr % 512) == 0) { /* On the sector boundary */ - if (--(fp->sect_clust)) { /* Decrement sector counter */ - sect = fp->curr_sect + 1; /* Next sector */ - } else { /* Next cluster */ + if (--(fp->sect_clust)) { /* Decrement left sector counter */ + sect = fp->curr_sect + 1; /* Get current sector */ + } else { /* On the cluster boundary, get next cluster */ clust = (fp->fptr == 0) ? fp->org_clust : get_cluster(fp->curr_clust); if ((clust < 2) || (clust >= fs->max_clust)) goto fr_error; fp->curr_clust = clust; /* Current cluster */ - sect = clust2sect(clust); /* Current sector */ - fp->sect_clust = fs->sects_clust; /* Re-initialize the sector counter */ + sect = clust2sect(clust); /* Get current sector */ + fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */ } #ifndef _FS_READONLY if (fp->flag & FA__DIRTY) { /* Flush file I/O buffer if needed */ @@ -772,8 +729,8 @@ FRESULT f_read ( } #endif fp->curr_sect = sect; /* Update current sector */ - cc = btr / 512; /* When left bytes >= 512 */ - if (cc) { /* Read maximum contiguous sectors */ + cc = btr / 512; /* When left bytes >= 512, */ + if (cc) { /* Read maximum contiguous sectors directly */ if (cc > fp->sect_clust) cc = fp->sect_clust; if (disk_read(rbuff, sect, cc) != RES_OK) goto fr_error; fp->sect_clust -= cc - 1; @@ -783,7 +740,7 @@ FRESULT f_read ( if (disk_read(fp->buffer, sect, 1) != RES_OK) /* Load the sector into file I/O buffer */ goto fr_error; } - rcnt = 512 - (fp->fptr % 512); /* Copy fractional bytes from file I/O buffer */ + rcnt = 512 - ((WORD)fp->fptr % 512); /* Copy fractional bytes from file I/O buffer */ if (rcnt > btr) rcnt = btr; memcpy(rbuff, &fp->buffer[fp->fptr % 512], rcnt); } @@ -825,28 +782,28 @@ FRESULT f_write ( for ( ; btw; /* Repeat until all data transferred */ wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { if ((fp->fptr % 512) == 0) { /* On the sector boundary */ - if (--(fp->sect_clust)) { /* Decrement sector counter */ - sect = fp->curr_sect + 1; /* Next sector */ - } else { /* Next cluster */ - if (fp->fptr == 0) { /* Top of the file */ + if (--(fp->sect_clust)) { /* Decrement left sector counter */ + sect = fp->curr_sect + 1; /* Get current sector */ + } else { /* On the cluster boundary, get next cluster */ + if (fp->fptr == 0) { /* Is top of the file */ clust = fp->org_clust; - if (clust == 0) /* No cluster is created */ + if (clust == 0) /* No cluster is created yet */ fp->org_clust = clust = create_chain(0); /* Create a new cluster chain */ } else { /* Middle or end of file */ clust = create_chain(fp->curr_clust); /* Trace or streach cluster chain */ } if ((clust < 2) || (clust >= fs->max_clust)) break; fp->curr_clust = clust; /* Current cluster */ - sect = clust2sect(clust); /* Current sector */ - fp->sect_clust = fs->sects_clust; /* Re-initialize the sector counter */ + sect = clust2sect(clust); /* Get current sector */ + fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */ } if (fp->flag & FA__DIRTY) { /* Flush file I/O buffer if needed */ if (disk_write(fp->buffer, fp->curr_sect, 1) != RES_OK) goto fw_error; fp->flag &= ~FA__DIRTY; } fp->curr_sect = sect; /* Update current sector */ - cc = btw / 512; /* When left bytes >= 512 */ - if (cc) { /* Write maximum contiguous sectors */ + cc = btw / 512; /* When left bytes >= 512, */ + if (cc) { /* Write maximum contiguous sectors directly */ if (cc > fp->sect_clust) cc = fp->sect_clust; if (disk_write(wbuff, sect, cc) != RES_OK) goto fw_error; fp->sect_clust -= cc - 1; @@ -857,7 +814,7 @@ FRESULT f_write ( (disk_read(fp->buffer, sect, 1) != RES_OK)) goto fw_error; } - wcnt = 512 - (fp->fptr % 512); /* Copy fractional bytes to file I/O buffer */ + wcnt = 512 - ((WORD)fp->fptr % 512); /* Copy fractional bytes to file I/O buffer */ if (wcnt > btw) wcnt = btw; memcpy(&fp->buffer[fp->fptr % 512], wbuff, wcnt); fp->flag |= FA__DIRTY; @@ -904,7 +861,7 @@ FRESULT f_lseek ( if (ofs) { ofs = (ofs - 1) / 512; /* Calcurate current sector */ sc = fs->sects_clust; /* Number of sectors in a cluster */ - fp->sect_clust = sc - (ofs % sc); /* Calcurate sector counter */ + fp->sect_clust = sc - ((BYTE)ofs % sc); /* Calcurate sector counter */ ofs /= sc; /* Number of clusters to skip */ clust = fp->org_clust; /* Seek to current cluster */ while (ofs--) @@ -993,11 +950,151 @@ FRESULT f_close ( -#ifndef _FS_MINIMUM +#if _FS_MINIMIZE <= 1 +/*---------------------------*/ +/* Initialize directroy scan */ + +FRESULT f_opendir ( + DIR *scan, /* Pointer to directory object to initialize */ + const char *path /* Pointer to the directory path, null str means the root */ +) +{ + FRESULT res; + BYTE *dir; + char fn[8+3+1]; + + + if ((res = check_mounted()) != FR_OK) return res; + + res = trace_path(scan, fn, path, &dir); /* Trace the directory path */ + + if (res == FR_OK) { /* Trace completed */ + if (dir != NULL) { /* It is not a root dir */ + if (*(dir+11) & AM_DIR) { /* The entry is a directory */ + scan->clust = ((DWORD)LD_WORD(dir+20) << 16) | LD_WORD(dir+26); + scan->sect = clust2sect(scan->clust); + scan->index = 0; + } else { /* The entry is not directory */ + res = FR_NO_FILE; + } + } + } + return res; +} + + + +/*----------------------------------*/ +/* Read Directory Entry in Sequense */ + +FRESULT f_readdir ( + DIR *scan, /* Pointer to the directory object */ + FILINFO *finfo /* Pointer to file information to return */ +) +{ + BYTE *dir, c; + FATFS *fs = FatFs; + + + if (!fs) return FR_NOT_ENABLED; + finfo->fname[0] = 0; + if ((disk_status() & STA_NOINIT) || !fs->fs_type) return FR_NOT_READY; + + while (scan->sect) { + if (!move_window(scan->sect)) return FR_RW_ERROR; + dir = &(fs->win[(scan->index & 15) * 32]); /* pointer to the directory entry */ + c = *dir; + if (c == 0) break; /* Has it reached to end of dir? */ + if ((c != 0xE5) && (c != '.') && !(*(dir+11) & AM_VOL)) /* Is it a valid entry? */ + get_fileinfo(finfo, dir); + if (!next_dir_entry(scan)) scan->sect = 0; /* Next entry */ + if (finfo->fname[0]) break; /* Found valid entry */ + } + + return FR_OK; +} + + + +#if _FS_MINIMIZE == 0 +/*-----------------*/ +/* Get File Status */ + +FRESULT f_stat ( + const char *path, /* Pointer to the file path */ + FILINFO *finfo /* Pointer to file information to return */ +) +{ + FRESULT res; + BYTE *dir; + DIR dirscan; + char fn[8+3+1]; + + + if ((res = check_mounted()) != FR_OK) return res; + + res = trace_path(&dirscan, fn, path, &dir); /* Trace the file path */ + + if (res == FR_OK) /* Trace completed */ + get_fileinfo(finfo, dir); + + return res; +} + + + +#ifndef _FS_READONLY +/*-----------------------------*/ +/* Get Number of Free Clusters */ + +FRESULT f_getfree ( + DWORD *nclust /* Pointer to the double word to return number of free clusters */ +) +{ + DWORD n, clust, sect; + BYTE fat, f, *p; + FRESULT res; + FATFS *fs = FatFs; + + + if ((res = check_mounted()) != FR_OK) return res; + + /* Count number of free clusters */ + fat = fs->fs_type; + n = 0; + if (fat == FS_FAT12) { + clust = 2; + do { + if ((WORD)get_cluster(clust) == 0) n++; + } while (++clust < fs->max_clust); + } else { + clust = fs->max_clust; + sect = fs->fatbase; + f = 0; p = 0; + do { + if (!f) { + if (!move_window(sect++)) return FR_RW_ERROR; + p = fs->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 (--clust); + } + + *nclust = n; + return FR_OK; +} + + + /*------------------------------*/ /* Delete a File or a Directory */ -#ifndef _FS_READONLY FRESULT f_unlink ( const char *path /* Pointer to the file or directory path */ ) @@ -1035,20 +1132,19 @@ FRESULT f_unlink ( } if (!move_window(dsect)) return FR_RW_ERROR; /* Mark the directory entry 'deleted' */ - *dir = 0xE5; fs->winflag = 1; + *dir = 0xE5; + fs->winflag = 1; if (!remove_chain(dclust)) return FR_RW_ERROR; /* Remove the cluster chain */ if (!move_window(0)) return FR_RW_ERROR; return FR_OK; } -#endif /* _FS_READONLY */ /*--------------------*/ /* Create a Directory */ -#ifndef _FS_READONLY FRESULT f_mkdir ( const char *path /* Pointer to the directory path */ ) @@ -1109,105 +1205,12 @@ FRESULT f_mkdir ( return FR_OK; } -#endif /* _FS_READONLY */ - - - -/*---------------------------*/ -/* Initialize directroy scan */ - -FRESULT f_opendir ( - DIR *scan, /* Pointer to directory object to initialize */ - const char *path /* Pointer to the directory path, null str means the root */ -) -{ - FRESULT res; - BYTE *dir; - char fn[8+3+1]; - - - if ((res = check_mounted()) != FR_OK) return res; - - res = trace_path(scan, fn, path, &dir); /* Trace the directory path */ - - if (res == FR_OK) { /* Trace completed */ - if (dir != NULL) { /* It is not a root dir */ - if (*(dir+11) & AM_DIR) { /* The entry is a directory */ - scan->clust = ((DWORD)LD_WORD(dir+20) << 16) | LD_WORD(dir+26); - scan->sect = clust2sect(scan->clust); - scan->index = 0; - } else { /* The entry is a file */ - res = FR_NO_PATH; - } - } - } - return res; -} - - - -/*----------------------------------*/ -/* Read Directory Entry in Sequense */ - -FRESULT f_readdir ( - DIR *scan, /* Pointer to the directory object */ - FILINFO *finfo /* Pointer to file information to return */ -) -{ - BYTE *dir, c; - FATFS *fs = FatFs; - - - if (!fs) return FR_NOT_ENABLED; - finfo->fname[0] = 0; - if ((disk_status() & STA_NOINIT) || !fs->fs_type) return FR_NOT_READY; - - while (scan->sect) { - if (!move_window(scan->sect)) return FR_RW_ERROR; - dir = &(fs->win[(scan->index & 15) * 32]); /* pointer to the directory entry */ - c = *dir; - if (c == 0) break; /* Has it reached to end of dir? */ - if ((c != 0xE5) && (c != '.') && !(*(dir+11) & AM_VOL)) /* Is it a valid entry? */ - get_fileinfo(finfo, dir); - if (!next_dir_entry(scan)) scan->sect = 0; /* Next entry */ - if (finfo->fname[0]) break; /* Found valid entry */ - } - - return FR_OK; -} - - - -/*-----------------*/ -/* Get File Status */ - -FRESULT f_stat ( - const char *path, /* Pointer to the file path */ - FILINFO *finfo /* Pointer to file information to return */ -) -{ - FRESULT res; - BYTE *dir; - DIR dirscan; - char fn[8+3+1]; - - - if ((res = check_mounted()) != FR_OK) return res; - - res = trace_path(&dirscan, fn, path, &dir); /* Trace the file path */ - - if (res == FR_OK) /* Trace completed */ - get_fileinfo(finfo, dir); - - return res; -} /*-----------------------*/ /* Change File Attribute */ -#ifndef _FS_READONLY FRESULT f_chmod ( const char *path, /* Pointer to the file path */ BYTE value, /* Attribute bits */ @@ -1226,19 +1229,65 @@ FRESULT f_chmod ( res = trace_path(&dirscan, fn, path, &dir); /* Trace the file path */ - if (res == FR_OK) { /* Trace completed */ + if (res == FR_OK) { /* Trace completed */ if (dir == NULL) { res = FR_NO_FILE; } else { mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ *(dir+11) = (value & mask) | (*(dir+11) & ~mask); /* Apply attribute change */ fs->winflag = 1; - if(!move_window(0)) res = FR_RW_ERROR; + if (!move_window(0)) res = FR_RW_ERROR; } } return res; } + + + +/*-----------------------*/ +/* Rename File/Directory */ + +FRESULT f_rename ( + const char *path_old, /* Pointer to the old name */ + const char *path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DWORD sect_old; + BYTE *dir_old, *dir_new, direntry[32-11]; + DIR dirscan; + char fn[8+3+1]; + FATFS *fs = FatFs; + + + if ((res = check_mounted()) != FR_OK) return res; + if (disk_status() & STA_PROTECT) return FR_WRITE_PROTECTED; + + res = trace_path(&dirscan, fn, path_old, &dir_old); /* Check old object */ + if (res != FR_OK) return res; /* The old object is not found */ + if (!dir_old) return FR_NO_FILE; + sect_old = fs->winsect; /* Save the object information */ + memcpy(direntry, dir_old+11, 32-11); + + res = trace_path(&dirscan, fn, path_new, &dir_new); /* Check new object */ + if (res == FR_OK) return FR_DENIED; /* The new object name is already existing */ + if (res != FR_NO_FILE) return res; + + dir_new = reserve_direntry(&dirscan); /* Reserve a directory entry */ + if (dir_new == NULL) return FR_DENIED; + memcpy(dir_new+11, direntry, 32-11); /* Create new entry */ + memcpy(dir_new, fn, 8+3); + *(dir_new+12) = fn[11]; + fs->winflag = 1; + + if (!move_window(sect_old)) return FR_RW_ERROR; /* Remove old entry */ + *dir_old = 0xE5; + fs->winflag = 1; + if (!move_window(0)) return FR_RW_ERROR; + + return FR_OK; +} #endif /* _FS_READONLY */ - -#endif /* _FS_MINIMUM */ +#endif /* _FS_MINIMIZE == 0 */ +#endif /* _FS_MINIMIZE <= 1 */ diff --git a/src/ff.h b/src/ff.h index 36d228c..ee180e8 100644 --- a/src/ff.h +++ b/src/ff.h @@ -1,26 +1,32 @@ /*--------------------------------------------------------------------------/ -/ FatFs - FAT file system module include file R0.02a (C)ChaN, 2006 +/ FatFs - FAT file system module include file R0.03 (C)ChaN, 2006 /---------------------------------------------------------------------------/ / FatFs module is an experimenal project to implement FAT file system to -/ cheap microcontrollers. This is opened for education, reserch and -/ development. You can use it for non-profit or profit use without any -/ limitation under your responsibility. +/ cheap microcontrollers. This is a free software and is opened for education, +/ research and development. You can use, modify and/or republish it for +/ non-profit or profit use without any restriction under your responsibility. /---------------------------------------------------------------------------*/ #ifndef _FATFS //#define _BYTE_ACC -/* This enables byte-by-byte access for multi-byte variables. It must be defined -on the big-endian processor, or to prevent address error. */ +/* The _BYTE_ACC enables byte-by-byte access for multi-byte variables. This +/ MUST be defined when multi-byte variable is stored in big-endian and/or +/ address miss-aligned access is prohibited. */ //#define _FS_READONLY -/* Read only configuration. This removes writing code for read-only applications. */ +/* Read only configuration. This removes writing functions, f_write, f_sync, +/ f_unlink, f_mkdir, f_chmod, f_rename and f_getfree. */ -//#define _FS_MINIMUM -/* Minimum configuration. This removes some functions to reduce module size. */ +#define _FS_MINIMIZE 0 +/* The _FS_MINIMIZE defines minimization level to remove some functions. +/ 0: Not minimized. +/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod and f_rename are removed. +/ 2: f_opendir and f_readdir are removed in addition to level 1. */ #define _USE_SJIS -/* This enables Shift-JIS code transparency, or only US-ASCII file name can be accepted. */ +/* When _USE_SJIS is defined, Shift-JIS code transparency is enabled, otherwise +/ only US-ASCII(7bit) code can be accepted as file/directory name. */ #include "integer.h" @@ -45,7 +51,7 @@ typedef struct _FATFS { DWORD dirbase; /* Root directory start sector (cluster# for FAT32) */ DWORD database; /* Data start sector */ DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[512]; /* Disk access window for Directory/FAT area */ + BYTE win[512]; /* Disk access window for Directory/FAT */ } FATFS; @@ -95,30 +101,27 @@ FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */ FRESULT f_read (FIL*, void*, WORD, WORD*); /* Read file */ FRESULT f_close (FIL*); /* Close file */ FRESULT f_lseek (FIL*, DWORD); /* Seek file pointer */ -FRESULT f_opendir (DIR*, const char*); /* Initialize to read a directory */ +FRESULT f_opendir (DIR*, const char*); /* Open a directory */ FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ FRESULT f_stat (const char*, FILINFO*); /* Get file status */ FRESULT f_getfree (DWORD*); /* Get number of free clusters */ -FRESULT f_mountdrv (); /* Force initialized the file system */ -#ifndef _FS_READONLY +FRESULT f_mountdrv (void); /* Force initialized the file system */ FRESULT f_write (FIL*, const void*, WORD, WORD*); /* Write file */ -FRESULT f_sync (FIL*); /* Flush cached information of a writing file */ +FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ FRESULT f_unlink (const char*); /* Delete a file or directory */ FRESULT f_mkdir (const char*); /* Create a directory */ FRESULT f_chmod (const char*, BYTE, BYTE); /* Change file attriburte */ -#endif +FRESULT f_rename (const char*, const char*); /* Rename a file or directory */ /* User defined function to give a current time to fatfs module */ -#ifndef _FS_READONLY -DWORD get_fattime(); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day(1-31) */ - /* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */ -#endif +DWORD get_fattime(void); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day(1-31) */ + /* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */ -/* File function return code */ +/* File function return code (FRESULT) */ #define FR_OK 0 #define FR_NOT_READY 1 @@ -128,13 +131,13 @@ DWORD get_fattime(); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day #define FR_DENIED 5 #define FR_DISK_FULL 6 #define FR_RW_ERROR 7 -#define FR_INCORRECT_DISK_CHANGE 9 -#define FR_WRITE_PROTECTED 10 -#define FR_NOT_ENABLED 11 -#define FR_NO_FILESYSTEM 12 +#define FR_INCORRECT_DISK_CHANGE 8 +#define FR_WRITE_PROTECTED 9 +#define FR_NOT_ENABLED 10 +#define FR_NO_FILESYSTEM 11 -/* File access control and file status flags */ +/* File access control and file status flags (FIL.flag) */ #define FA_READ 0x01 #define FA_OPEN_EXISTING 0x00 @@ -148,19 +151,20 @@ DWORD get_fattime(); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day #define FA__ERROR 0x80 -/* FAT type signature (fs_type) */ +/* FAT type signature (FATFS.fs_type) */ #define FS_FAT12 1 #define FS_FAT16 2 #define FS_FAT32 3 -/* File attribute mask for directory entry */ +/* File attribute bits for directory entry */ -#define AM_RDO 0x01 /* Read Only */ +#define AM_RDO 0x01 /* Read only */ #define AM_HID 0x02 /* Hidden */ #define AM_SYS 0x04 /* System */ -#define AM_VOL 0x08 /* Volume Label */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ #define AM_DIR 0x10 /* Directory */ #define AM_ARC 0x20 /* Archive */ @@ -169,15 +173,15 @@ DWORD get_fattime(); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day /* Multi-byte word access macros */ #ifdef _BYTE_ACC -#define LD_WORD(ptr) (((WORD)*(BYTE*)(ptr+1)<<8)|*(ptr)) -#define LD_DWORD(ptr) (((DWORD)*(BYTE*)(ptr+3)<<24)|((DWORD)*(BYTE*)(ptr+2)<<16)|((WORD)*(BYTE*)(ptr+1)<<8)|*(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(BYTE*)(ptr)=val; *(BYTE*)(ptr+1)=val>>8 -#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=val; *(BYTE*)(ptr+1)=val>>8; *(BYTE*)(ptr+2)=val>>16; *(BYTE*)(ptr+3)=val>>24 +#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24) #else -#define LD_WORD(ptr) (*(WORD*)(BYTE*)(ptr)) -#define LD_DWORD(ptr) (*(DWORD*)(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(val) -#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(val) +#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) +#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) #endif diff --git a/src/integer.h b/src/integer.h index 651f34e..8c02df2 100644 --- a/src/integer.h +++ b/src/integer.h @@ -1,8 +1,14 @@ #ifndef _INTEGER typedef unsigned char BYTE; +typedef unsigned char UCHAR; +typedef char CHAR; typedef unsigned short WORD; +typedef unsigned short USHORT; +typedef short SHORT; typedef unsigned long DWORD; +typedef unsigned long ULONG; +typedef long LONG; typedef unsigned char BOOL; #define FALSE 0 diff --git a/src/tff.c b/src/tff.c index 1ff7cbb..fcf4d01 100644 --- a/src/tff.c +++ b/src/tff.c @@ -1,22 +1,23 @@ /*--------------------------------------------------------------------------/ -/ Tiny FatFs - FAT file system module R0.02a (C)ChaN, 2006 +/ FatFs - FAT file system module R0.03 (C)ChaN, 2006 /---------------------------------------------------------------------------/ / FatFs module is an experimenal project to implement FAT file system to -/ cheap microcontrollers. This is a freeware and is opened for education, -/ research and development. You can use, modify and republish it for -/ non-profit or profit use without any limitation under your responsibility. +/ cheap microcontrollers. This is a free software and is opened for education, +/ research and development. You can use, modify and/or republish it for +/ non-profit or profit use without any restriction under your responsibility. /---------------------------------------------------------------------------/ -/ Feb 26, 2006 R0.00 Prototype -/ Apr 29, 2006 R0.01 First stable version +/ Feb 26, 2006 R0.00 Prototype. +/ Apr 29, 2006 R0.01 First stable version. / Jun 01, 2006 R0.02 Added FAT12. Removed unbuffered mode. / Fixed a problem on small (<32M) patition. / Jun 10, 2006 R0.02a Added a configuration option (_FS_MINIMUM). +/ Sep 22, 2006 R0.03 Added f_rename(). +/ Changed option _FS_MINIMUM to _FS_MINIMIZE. /---------------------------------------------------------------------------*/ - #include #include "tff.h" /* Tiny-FatFs declarations */ -#include "diskio.h" /* Include file for user provided functions */ +#include "diskio.h" /* Include file for user provided disk functions */ FATFS *FatFs; /* Pointer to the file system object */ @@ -67,7 +68,9 @@ BOOL move_window ( /* Get a Cluster Status */ static -WORD get_cluster (WORD clust) /* Cluster# to get the link information */ +WORD get_cluster ( + WORD clust /* Cluster# to get the link information */ +) { WORD wc, bc; DWORD fatsect; @@ -76,19 +79,21 @@ WORD get_cluster (WORD clust) /* Cluster# to get the link information */ if ((clust >= 2) && (clust < fs->max_clust)) { /* Valid cluster# */ fatsect = fs->fatbase; - if (fs->fs_type == FS_FAT12) { + switch (fs->fs_type) { + case FS_FAT12 : bc = clust * 3 / 2; - if (!move_window(fatsect + bc / 512)) return 1; + if (!move_window(fatsect + bc / 512)) break; wc = fs->win[bc % 512]; bc++; - if (!move_window(fatsect + bc / 512)) return 1; + if (!move_window(fatsect + bc / 512)) break; wc |= (WORD)fs->win[bc % 512] << 8; return (clust & 1) ? (wc >> 4) : (wc & 0xFFF); - } else { - if (!move_window(fatsect + clust / 256)) return 1; + + case FS_FAT16 : + if (!move_window(fatsect + clust / 256)) break; return LD_WORD(&(fs->win[(clust * 2) % 512])); } } - return 1; /* Return with 1 means function failed */ + return 1; /* There is no cluster information, or an error occured */ } @@ -115,7 +120,8 @@ BOOL put_cluster ( if (!move_window(fatsect + bc / 512)) return FALSE; p = &fs->win[bc % 512]; *p = (clust & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; - fs->winflag = 1; bc++; + bc++; + fs->winflag = 1; if (!move_window(fatsect + bc / 512)) return FALSE; p = &fs->win[bc % 512]; *p = (clust & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); @@ -143,9 +149,11 @@ BOOL remove_chain ( WORD nxt; - while ((nxt = get_cluster(clust)) >= 2) { - if (!put_cluster(clust, 0)) return FALSE; - clust = nxt; + if (clust) { + while ((nxt = get_cluster(clust)) >= 2) { + if (!put_cluster(clust, 0)) return FALSE; + clust = nxt; + } } return TRUE; } @@ -158,7 +166,7 @@ BOOL remove_chain ( #ifndef _FS_READONLY static -DWORD create_chain ( +WORD create_chain ( WORD clust /* Cluster# to stretch, 0 means create new */ ) { @@ -220,7 +228,7 @@ DWORD clust2sect ( static BYTE check_fs ( - DWORD sect /* Sector# to check if it is a FAT boot record or not */ + DWORD sect /* Sector# to check if it is a FAT boot record or not */ ) { static const char fatsign[] = "FAT12FAT16"; @@ -278,11 +286,11 @@ BOOL next_dir_entry ( /*--------------------------------------*/ /* Get File Status from Directory Entry */ -#ifndef _FS_MINIMUM +#if _FS_MINIMIZE <= 1 static void get_fileinfo ( - FILINFO *finfo, /* Ptr to Store the File Information */ - const BYTE *dir /* Ptr to the Directory Entry */ + FILINFO *finfo, /* Ptr to store the File Information */ + const BYTE *dir /* Ptr to the directory entry */ ) { BYTE n, c, a; @@ -314,11 +322,12 @@ void get_fileinfo ( finfo->fdate = LD_WORD(dir+24); /* Date */ finfo->ftime = LD_WORD(dir+22); /* Time */ } -#endif /* _FS_READONLY */ +#endif /* _FS_MINIMIZE <= 1 */ -/*-----------------------------------------------------*/ -/* Pick a Paragraph and Create Name in Directory Entry */ + +/*-------------------------------------------------------------------*/ +/* Pick a Paragraph and Create the Name in Format of Directory Entry */ static char make_dirfile ( @@ -399,9 +408,8 @@ FRESULT trace_path ( FATFS *fs = FatFs; /* Initialize directory object */ - clust = fs->dirbase; scan->clust = scan->sclust = 0; - scan->sect = clust; + scan->sect = fs->dirbase; scan->index = 0; while ((*path == ' ') || (*path == '/')) path++; /* Skip leading spaces */ @@ -516,10 +524,10 @@ FRESULT check_mounted () /*--------------------------------------------------------------------------*/ -/*--------------------------------------------------------*/ -/* Load File System Information and Initialize the Module */ +/*----------------------------------------------------------*/ +/* Load File System Information and Initialize FatFs Module */ -FRESULT f_mountdrv () +FRESULT f_mountdrv (void) { BYTE fat; DWORD sect, fatend, maxsect; @@ -559,7 +567,7 @@ FRESULT f_mountdrv () maxsect = LD_DWORD(&(fs->win[0x20])); /* Calculate maximum cluster number */ if (!maxsect) maxsect = LD_WORD(&(fs->win[0x13])); - fs->max_clust = (maxsect - fs->database + sect) / fs->sects_clust + 2; + fs->max_clust = (WORD)((maxsect - fs->database + sect) / fs->sects_clust + 2); fs->files = 0; return FR_OK; @@ -567,51 +575,8 @@ FRESULT f_mountdrv () -/*-----------------------------*/ -/* Get Number of Free Clusters */ - -FRESULT f_getfree ( - DWORD *nclust /* Pointer to the double word to return number of free clusters */ -) -{ - DWORD n, sect; - WORD clust; - BYTE f, *p; - FRESULT res; - FATFS *fs = FatFs; - - - if ((res = check_mounted()) != FR_OK) return res; - - /* Count number of free clusters */ - n = 0; - if (fs->fs_type == FS_FAT12) { - clust = 2; - do { - if (get_cluster(clust) == 0) n++; - } while (++clust < fs->max_clust); - } else { - clust = fs->max_clust; - sect = fs->fatbase; - f = 0; p = 0; - do { - if (!f) { - if (!move_window(sect++)) return FR_RW_ERROR; - p = fs->win; - } - if (LD_WORD(p) == 0) n++; - p += 2; f += 1; - } while (--clust); - } - - *nclust = n; - return FR_OK; -} - - - -/*---------------------*/ -/* Open or Create File */ +/*-----------------------*/ +/* Open or Create a File */ FRESULT f_open ( FIL *fp, /* Pointer to the buffer of new file object to create */ @@ -646,7 +611,7 @@ FRESULT f_open ( memcpy(dir, fn, 8+3); /* Initialize the new entry */ *(dir+12) = fn[11]; memset(dir+13, 0, 32-13); - } else { /* File already exists */ + } else { /* Any object is already existing */ if ((dir == NULL) || (*(dir+11) & (AM_RDO|AM_DIR))) /* Could not overwrite (R/O or DIR) */ return FR_DENIED; if (mode & FA_CREATE_ALWAYS) { /* Resize it to zero */ @@ -716,23 +681,23 @@ FRESULT f_read ( if (fp->flag & FA__ERROR) return FR_RW_ERROR; /* Check error flag */ if (!(fp->flag & FA_READ)) return FR_DENIED; /* Check access mode */ ln = fp->fsize - fp->fptr; - if (btr > ln) btr = ln; /* Truncate read count by number of bytes left */ + if (btr > ln) btr = (WORD)ln; /* Truncate read count by number of bytes left */ for ( ; btr; /* Repeat until all data transferred */ rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) { if ((fp->fptr % 512) == 0) { /* On the sector boundary */ - if (--(fp->sect_clust)) { /* Decrement sector counter */ - sect = fp->curr_sect + 1; /* Next sector */ - } else { /* Next cluster */ + if (--(fp->sect_clust)) { /* Decrement left sector counter */ + sect = fp->curr_sect + 1; /* Get current sector */ + } else { /* On the cluster boundary, get next cluster */ clust = (fp->fptr == 0) ? fp->org_clust : get_cluster(fp->curr_clust); if ((clust < 2) || (clust >= fs->max_clust)) goto fr_error; fp->curr_clust = clust; /* Current cluster */ - sect = clust2sect(clust); /* Current sector */ - fp->sect_clust = fs->sects_clust; /* Re-initialize the sector counter */ + sect = clust2sect(clust); /* Get current sector */ + fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */ } fp->curr_sect = sect; /* Update current sector */ - cc = btr / 512; /* When left bytes >= 512 */ - if (cc) { /* Read maximum contiguous sectors */ + cc = btr / 512; /* When left bytes >= 512, */ + if (cc) { /* Read maximum contiguous sectors directly */ if (cc > fp->sect_clust) cc = fp->sect_clust; if (disk_read(rbuff, sect, cc) != RES_OK) goto fr_error; fp->sect_clust -= cc - 1; @@ -741,7 +706,7 @@ FRESULT f_read ( } } if (!move_window(fp->curr_sect)) goto fr_error; /* Move sector window */ - rcnt = 512 - (fp->fptr % 512); /* Copy fractional bytes from sector window */ + rcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes from sector window */ if (rcnt > btr) rcnt = btr; memcpy(rbuff, &fs->win[fp->fptr % 512], rcnt); } @@ -783,24 +748,24 @@ FRESULT f_write ( for ( ; btw; /* Repeat until all data transferred */ wbuff += wcnt, fp->fptr += wcnt, *bw += wcnt, btw -= wcnt) { if ((fp->fptr % 512) == 0) { /* On the sector boundary */ - if (--(fp->sect_clust)) { /* Decrement sector counter */ - sect = fp->curr_sect + 1; /* Next sector */ - } else { /* Next cluster */ - if (fp->fptr == 0) { /* Top of the file */ + if (--(fp->sect_clust)) { /* Decrement left sector counter */ + sect = fp->curr_sect + 1; /* Get current sector */ + } else { /* On the cluster boundary, get next cluster */ + if (fp->fptr == 0) { /* Is top of the file */ clust = fp->org_clust; - if (clust == 0) /* No cluster is created */ + if (clust == 0) /* No cluster is created yet */ fp->org_clust = clust = create_chain(0); /* Create a new cluster chain */ } else { /* Middle or end of file */ clust = create_chain(fp->curr_clust); /* Trace or streach cluster chain */ } if ((clust < 2) || (clust >= fs->max_clust)) break; fp->curr_clust = clust; /* Current cluster */ - sect = clust2sect(clust); /* Current sector */ - fp->sect_clust = fs->sects_clust; /* Re-initialize the sector counter */ + sect = clust2sect(clust); /* Get current sector */ + fp->sect_clust = fs->sects_clust; /* Re-initialize the left sector counter */ } fp->curr_sect = sect; /* Update current sector */ - cc = btw / 512; /* When left bytes >= 512 */ - if (cc) { /* Write maximum contiguous sectors */ + cc = btw / 512; /* When left bytes >= 512, */ + if (cc) { /* Write maximum contiguous sectors directly */ if (cc > fp->sect_clust) cc = fp->sect_clust; if (disk_write(wbuff, sect, cc) != RES_OK) goto fw_error; fp->sect_clust -= cc - 1; @@ -813,7 +778,7 @@ FRESULT f_write ( } } if (!move_window(fp->curr_sect)) goto fw_error; /* Move sector window */ - wcnt = 512 - (fp->fptr % 512); /* Copy fractional bytes bytes to sector window */ + wcnt = 512 - (WORD)(fp->fptr % 512); /* Copy fractional bytes bytes to sector window */ if (wcnt > btw) wcnt = btw; memcpy(&fs->win[fp->fptr % 512], wbuff, wcnt); fs->winflag = 1; @@ -854,7 +819,7 @@ FRESULT f_lseek ( if (ofs) { ofs = (ofs - 1) / 512; /* Calcurate current sector */ sc = fs->sects_clust; /* Number of sectors in a cluster */ - fp->sect_clust = sc - (ofs % sc); /* Calcurate sector counter */ + fp->sect_clust = sc - ((BYTE)ofs % sc); /* Calcurate sector counter */ ofs /= sc; /* Number of clusters to skip */ clust = fp->org_clust; /* Seek to current cluster */ while (ofs--) @@ -932,11 +897,146 @@ FRESULT f_close ( -#ifndef _FS_MINIMUM -/*----------------------------*/ -/* Delete a File or Directory */ +#if _FS_MINIMIZE <= 1 +/*---------------------------*/ +/* Initialize directroy scan */ + +FRESULT f_opendir ( + DIR *scan, /* Pointer to directory object to initialize */ + const char *path /* Pointer to the directory path, null str means the root */ +) +{ + FRESULT res; + BYTE *dir; + char fn[8+3+1]; + + + if ((res = check_mounted()) != FR_OK) return res; + + res = trace_path(scan, fn, path, &dir); /* Trace the directory path */ + + if (res == FR_OK) { /* Trace completed */ + if (dir != NULL) { /* It is not a root dir */ + if (*(dir+11) & AM_DIR) { /* The entry is a directory */ + scan->clust = LD_WORD(dir+26); + scan->sect = clust2sect(scan->clust); + scan->index = 0; + } else { /* The entry is not directory */ + res = FR_NO_FILE; + } + } + } + return res; +} + + + +/*----------------------------------*/ +/* Read Directory Entry in Sequense */ + +FRESULT f_readdir ( + DIR *scan, /* Pointer to the directory object */ + FILINFO *finfo /* Pointer to file information to return */ +) +{ + BYTE *dir, c; + FATFS *fs = FatFs; + + + if (!fs) return FR_NOT_ENABLED; + finfo->fname[0] = 0; + if ((disk_status() & STA_NOINIT) || !fs->fs_type) return FR_NOT_READY; + + while (scan->sect) { + if (!move_window(scan->sect)) return FR_RW_ERROR; + dir = &(fs->win[(scan->index & 15) * 32]); /* pointer to the directory entry */ + c = *dir; + if (c == 0) break; /* Has it reached to end of dir? */ + if ((c != 0xE5) && (c != '.') && !(*(dir+11) & AM_VOL)) /* Is it a valid entry? */ + get_fileinfo(finfo, dir); + if (!next_dir_entry(scan)) scan->sect = 0; /* Next entry */ + if (finfo->fname[0]) break; /* Found valid entry */ + } + + return FR_OK; +} + + + +#if _FS_MINIMIZE == 0 +/*-----------------*/ +/* Get File Status */ + +FRESULT f_stat ( + const char *path, /* Pointer to the file path */ + FILINFO *finfo /* Pointer to file information to return */ +) +{ + FRESULT res; + BYTE *dir; + DIR dirscan; + char fn[8+3+1]; + + + if ((res = check_mounted()) != FR_OK) return res; + + res = trace_path(&dirscan, fn, path, &dir); /* Trace the file path */ + + if (res == FR_OK) /* Trace completed */ + get_fileinfo(finfo, dir); + + return res; +} + + #ifndef _FS_READONLY +/*-----------------------------*/ +/* Get Number of Free Clusters */ + +FRESULT f_getfree ( + DWORD *nclust /* Pointer to the double word to return number of free clusters */ +) +{ + DWORD n, sect; + WORD clust; + BYTE f, *p; + FRESULT res; + FATFS *fs = FatFs; + + + if ((res = check_mounted()) != FR_OK) return res; + + /* Count number of free clusters */ + n = 0; + if (fs->fs_type == FS_FAT12) { + clust = 2; + do { + if (get_cluster(clust) == 0) n++; + } while (++clust < fs->max_clust); + } else { + clust = fs->max_clust; + sect = fs->fatbase; + f = 0; p = 0; + do { + if (!f) { + if (!move_window(sect++)) return FR_RW_ERROR; + p = fs->win; + } + if (LD_WORD(p) == 0) n++; + p += 2; f += 1; + } while (--clust); + } + + *nclust = n; + return FR_OK; +} + + + +/*------------------------------*/ +/* Delete a File or a Directory */ + FRESULT f_unlink ( const char *path /* Pointer to the file or directory path */ ) @@ -975,20 +1075,19 @@ FRESULT f_unlink ( } if (!move_window(dsect)) return FR_RW_ERROR; /* Mark the directory entry 'deleted' */ - *dir = 0xE5; fs->winflag = 1; + *dir = 0xE5; + fs->winflag = 1; if (!remove_chain(dclust)) return FR_RW_ERROR; /* Remove the cluster chain */ if (!move_window(0)) return FR_RW_ERROR; return FR_OK; } -#endif /* _FS_READONLY */ /*--------------------*/ /* Create a Directory */ -#ifndef _FS_READONLY FRESULT f_mkdir ( const char *path /* Pointer to the directory path */ ) @@ -1047,105 +1146,12 @@ FRESULT f_mkdir ( return FR_OK; } -#endif /* _FS_READONLY */ - - - -/*---------------------------*/ -/* Initialize directroy scan */ - -FRESULT f_opendir ( - DIR *scan, /* Pointer to directory object to initialize */ - const char *path /* Pointer to the directory path, null str means the root */ -) -{ - FRESULT res; - BYTE *dir; - char fn[8+3+1]; - - - if ((res = check_mounted()) != FR_OK) return res; - - res = trace_path(scan, fn, path, &dir); /* Trace the directory path */ - - if (res == FR_OK) { /* Trace completed */ - if (dir != NULL) { /* It is not a root dir */ - if (*(dir+11) & AM_DIR) { /* The entry is a directory */ - scan->clust = LD_WORD(dir+26); - scan->sect = clust2sect(scan->clust); - scan->index = 0; - } else { /* The entry is a file */ - res = FR_NO_PATH; - } - } - } - return res; -} - - - -/*----------------------------------*/ -/* Read Directory Entry in Sequense */ - -FRESULT f_readdir ( - DIR *scan, /* Pointer to the directory object */ - FILINFO *finfo /* Pointer to file information to return */ -) -{ - BYTE *dir, c; - FATFS *fs = FatFs; - - - if (!fs) return FR_NOT_ENABLED; - finfo->fname[0] = 0; - if ((disk_status() & STA_NOINIT) || !fs->fs_type) return FR_NOT_READY; - - while (scan->sect) { - if (!move_window(scan->sect)) return FR_RW_ERROR; - dir = &(fs->win[(scan->index & 15) * 32]); /* pointer to the directory entry */ - c = *dir; - if (c == 0) break; /* Has it reached to end of dir? */ - if ((c != 0xE5) && (c != '.') && !(*(dir+11) & AM_VOL)) /* Is it a valid entry? */ - get_fileinfo(finfo, dir); - if (!next_dir_entry(scan)) scan->sect = 0; /* Next entry */ - if (finfo->fname[0]) break; /* Found valid entry */ - } - - return FR_OK; -} - - - -/*-----------------*/ -/* Get File Status */ - -FRESULT f_stat ( - const char *path, /* Pointer to the file path */ - FILINFO *finfo /* Pointer to file information to return */ -) -{ - FRESULT res; - BYTE *dir; - DIR dirscan; - char fn[8+3+1]; - - - if ((res = check_mounted()) != FR_OK) return res; - - res = trace_path(&dirscan, fn, path, &dir); /* Trace the file path */ - - if (res == FR_OK) /* Trace completed */ - get_fileinfo(finfo, dir); - - return res; -} /*-----------------------*/ /* Change File Attribute */ -#ifndef _FS_READONLY FRESULT f_chmod ( const char *path, /* Pointer to the file path */ BYTE value, /* Attribute bits */ @@ -1164,19 +1170,65 @@ FRESULT f_chmod ( res = trace_path(&dirscan, fn, path, &dir); /* Trace the file path */ - if (res == FR_OK) { /* Trace completed */ + if (res == FR_OK) { /* Trace completed */ if (dir == NULL) { res = FR_NO_FILE; } else { mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ *(dir+11) = (value & mask) | (*(dir+11) & ~mask); /* Apply attribute change */ fs->winflag = 1; - if(!move_window(0)) res = FR_RW_ERROR; + if (!move_window(0)) res = FR_RW_ERROR; } } return res; } + + + +/*-----------------------*/ +/* Rename File/Directory */ + +FRESULT f_rename ( + const char *path_old, /* Pointer to the old name */ + const char *path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DWORD sect_old; + BYTE *dir_old, *dir_new, direntry[32-11]; + DIR dirscan; + char fn[8+3+1]; + FATFS *fs = FatFs; + + + if ((res = check_mounted()) != FR_OK) return res; + if (disk_status() & STA_PROTECT) return FR_WRITE_PROTECTED; + + res = trace_path(&dirscan, fn, path_old, &dir_old); /* Check old object */ + if (res != FR_OK) return res; /* The old object is not found */ + if (!dir_old) return FR_NO_FILE; + sect_old = fs->winsect; /* Save the object information */ + memcpy(direntry, dir_old+11, 32-11); + + res = trace_path(&dirscan, fn, path_new, &dir_new); /* Check new object */ + if (res == FR_OK) return FR_DENIED; /* The new object name is already existing */ + if (res != FR_NO_FILE) return res; + + dir_new = reserve_direntry(&dirscan); /* Reserve a directory entry */ + if (dir_new == NULL) return FR_DENIED; + memcpy(dir_new+11, direntry, 32-11); /* Create new entry */ + memcpy(dir_new, fn, 8+3); + *(dir_new+12) = fn[11]; + fs->winflag = 1; + + if (!move_window(sect_old)) return FR_RW_ERROR; /* Remove old entry */ + *dir_old = 0xE5; + fs->winflag = 1; + if (!move_window(0)) return FR_RW_ERROR; + + return FR_OK; +} #endif /* _FS_READONLY */ - -#endif /* _FS_MINIMUM */ +#endif /* _FS_MINIMIZE == 0 */ +#endif /* _FS_MINIMIZE <= 1 */ diff --git a/src/tff.h b/src/tff.h index 265d68a..957fd67 100644 --- a/src/tff.h +++ b/src/tff.h @@ -1,26 +1,32 @@ /*--------------------------------------------------------------------------/ -/ Tiny-FatFs - FAT file system module include file R0.02a (C)ChaN, 2006 +/ Tiny-FatFs - FAT file system module include file R0.03 (C)ChaN, 2006 /---------------------------------------------------------------------------/ / FatFs module is an experimenal project to implement FAT file system to -/ cheap microcontrollers. This is opened for education, reserch and -/ development. You can use it for non-profit or profit use without any -/ limitation under your responsibility. +/ cheap microcontrollers. This is a free software and is opened for education, +/ research and development. You can use, modify and/or republish it for +/ non-profit or profit use without any restriction under your responsibility. /---------------------------------------------------------------------------*/ #ifndef _FATFS //#define _BYTE_ACC -/* This enables byte-by-byte access for multi-byte variables. It must be defined -on the big-endian processor, or to prevent address error. */ +/* The _BYTE_ACC enables byte-by-byte access for multi-byte variables. This +/ MUST be defined when multi-byte variable is stored in big-endian and/or +/ address miss-aligned access is prohibited. */ //#define _FS_READONLY -/* Read only configuration. This removes writing code for read-only applications. */ +/* Read only configuration. This removes writing functions, f_write, f_sync, +/ f_unlink, f_mkdir, f_chmod, f_rename and g_getfree. */ -//#define _FS_MINIMUM -/* Minimum configuration. This removes some functions to reduce module size. */ +#define _FS_MINIMIZE 0 +/* The _FS_MINIMIZE defines minimization level to remove some functions. +/ 0: Not minimized. +/ 1: f_stat, f_getfree, f_unlink, f_mkdir, f_chmod and f_rename are removed. +/ 2: f_opendir and f_readdir are removed in addition to level 1. */ #define _USE_SJIS -/* This enables Shift-JIS code transparency, or only US-ASCII file name can be accepted. */ +/* When _USE_SJIS is defined, Shift-JIS code transparency is enabled, otherwise +/ only US-ASCII(7bit) code can be accepted as file/directory name. */ #include "integer.h" @@ -30,7 +36,7 @@ on the big-endian processor, or to prevent address error. */ typedef unsigned char FRESULT; -/* File system object */ +/* File system object structure */ typedef struct _FATFS { BYTE fs_type; /* FAT type */ BYTE files; /* Number of files currently opend */ @@ -45,11 +51,11 @@ typedef struct _FATFS { DWORD dirbase; /* Root directory start sector (cluster# for FAT32) */ DWORD database; /* Data start sector */ DWORD winsect; /* Current sector appearing in the win[] */ - BYTE win[512]; /* Disk access window */ + BYTE win[512]; /* Disk access window for Directory/FAT/File */ } FATFS; -/* Directory scan object */ +/* Directory object structure */ typedef struct _DIR { WORD sclust; /* Start cluster */ WORD clust; /* Current cluster */ @@ -58,10 +64,10 @@ typedef struct _DIR { } DIR; -/* File object */ +/* File object structure */ typedef struct _FIL { - DWORD fptr; /* File Pointer */ - DWORD fsize; /* File Size */ + DWORD fptr; /* File R/W pointer */ + DWORD fsize; /* File size */ WORD org_clust; /* File start cluster */ WORD curr_clust; /* Current cluster */ DWORD curr_sect; /* Current sector */ @@ -80,12 +86,13 @@ typedef struct _FILINFO { WORD fdate; /* Date */ WORD ftime; /* Time */ BYTE fattrib; /* Attribute */ - char fname[8+1+3+1]; /* File/Directory name (8.3 format) */ + char fname[8+1+3+1]; /* Name (8.3 format) */ } FILINFO; -/* fatfs module application interface */ +/*-----------------------------------------------------*/ +/* FatFs module application interface */ extern FATFS *FatFs; /* Pointer to active file system object */ @@ -93,30 +100,27 @@ FRESULT f_open (FIL*, const char*, BYTE); /* Open or create a file */ FRESULT f_read (FIL*, void*, WORD, WORD*); /* Read file */ FRESULT f_close (FIL*); /* Close file */ FRESULT f_lseek (FIL*, DWORD); /* Seek file pointer */ -FRESULT f_opendir (DIR*, const char*); /* Initialize to read a directory */ +FRESULT f_opendir (DIR*, const char*); /* Open a directory */ FRESULT f_readdir (DIR*, FILINFO*); /* Read a directory item */ FRESULT f_stat (const char*, FILINFO*); /* Get file status */ FRESULT f_getfree (DWORD*); /* Get number of free clusters */ -FRESULT f_mountdrv (); /* Force initialized the file system */ -#ifndef _FS_READONLY +FRESULT f_mountdrv (void); /* Force initialized the file system */ FRESULT f_write (FIL*, const void*, WORD, WORD*); /* Write file */ -FRESULT f_sync (FIL*); /* Flush cached information of a writing file */ +FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ FRESULT f_unlink (const char*); /* Delete a file or directory */ FRESULT f_mkdir (const char*); /* Create a directory */ FRESULT f_chmod (const char*, BYTE, BYTE); /* Change file attriburte */ -#endif +FRESULT f_rename (const char*, const char*); /* Rename a file or directory */ /* User defined function to give a current time to fatfs module */ -#ifndef _FS_READONLY -DWORD get_fattime(); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day(1-31) */ - /* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */ -#endif +DWORD get_fattime(void); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day(1-31) */ + /* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */ -/* File function return code */ +/* File function return code (FRESULT) */ #define FR_OK 0 #define FR_NOT_READY 1 @@ -126,13 +130,13 @@ DWORD get_fattime(); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day #define FR_DENIED 5 #define FR_DISK_FULL 6 #define FR_RW_ERROR 7 -#define FR_INCORRECT_DISK_CHANGE 9 -#define FR_WRITE_PROTECTED 10 -#define FR_NOT_ENABLED 11 -#define FR_NO_FILESYSTEM 12 +#define FR_INCORRECT_DISK_CHANGE 8 +#define FR_WRITE_PROTECTED 9 +#define FR_NOT_ENABLED 10 +#define FR_NO_FILESYSTEM 11 -/* File access control and file status flags */ +/* File access control and file status flags (FIL.flag) */ #define FA_READ 0x01 #define FA_OPEN_EXISTING 0x00 @@ -145,18 +149,19 @@ DWORD get_fattime(); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day #define FA__ERROR 0x80 -/* FAT type signature (fs_type) */ +/* FAT type signature (FATFS.fs_type) */ #define FS_FAT12 1 #define FS_FAT16 2 -/* File attribute mask for directory entry */ +/* File attribute bits for directory entry */ -#define AM_RDO 0x01 /* Read Only */ +#define AM_RDO 0x01 /* Read only */ #define AM_HID 0x02 /* Hidden */ #define AM_SYS 0x04 /* System */ -#define AM_VOL 0x08 /* Volume Label */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ #define AM_DIR 0x10 /* Directory */ #define AM_ARC 0x20 /* Archive */ @@ -165,15 +170,15 @@ DWORD get_fattime(); /* 31-25: Year(0-127 +1980), 24-21: Month(1-12), 20-16: Day /* Multi-byte word access macros */ #ifdef _BYTE_ACC -#define LD_WORD(ptr) (((WORD)*(BYTE*)(ptr+1)<<8)|*(ptr)) -#define LD_DWORD(ptr) (((DWORD)*(BYTE*)(ptr+3)<<24)|((DWORD)*(BYTE*)(ptr+2)<<16)|((WORD)*(BYTE*)(ptr+1)<<8)|*(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(BYTE*)(ptr)=val; *(BYTE*)(ptr+1)=val>>8 -#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=val; *(BYTE*)(ptr+1)=val>>8; *(BYTE*)(ptr+2)=val>>16; *(BYTE*)(ptr+3)=val>>24 +#define LD_WORD(ptr) (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8) +#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24) #else -#define LD_WORD(ptr) (*(WORD*)(BYTE*)(ptr)) -#define LD_DWORD(ptr) (*(DWORD*)(BYTE*)(ptr)) -#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(val) -#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(val) +#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr)) +#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr)) +#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val) +#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val) #endif