FatFs - f_expand

## f_expand

ファイルに連続したデータ領域を割り当てます。

    FRESULT f_expand (
      FIL*    fp,  /* [IN] ファイル オブジェクト構造体へのポインタ */
      FSIZE_t fsz, /* [IN] 割り当てサイズ */
      BYTE    opt  /* [IN] 動作オプション */
    );

#### Parameters

fp
  対象となるファイル オブジェクト構造体へのポインタを指定します。
fsz
  ファイルに割り当てるバイト単位のサイズ。データ型`FSIZE_t`は、`DWORD`(32ビット)または`QWORD`(64ビット)のエリアスで、exFATサポートの有無により切り替わります。
opt
  実際に割り当てを行うかどうか指定するフラグ。

#### Return Values

FR_OK, FR_DISK_ERR, FR_INT_ERR, FR_DENIED, FR_INVALID_OBJECT, FR_TIMEOUT

#### 解説

`opt`に1を指定すると、ファイルに連続したデータ領域を割り当てます。`f_lseek`によるサイズ拡張とは異なり、対象ファイルのサイズは0(つまりデータ領域未割り当て)でなければなりません。また、リード/ライト ポインタは、ファイル先頭に留まります。この関数により割り当てられたファイルの内容は未定義なので、それに対して何の前提も持つべきではありません。この関数は、次の理由により`FR_DENIED`で失敗することがあります。

- ボリューム上に連続した空き領域が見つからなかった。
- ファイルのサイズが0ではなかった。
- ファイルが非書き込みモードで開かれている。
- 指定されたファイル サイズが無効。(FATボリューム上で >=4GiB)

`opt`に0を指定したときは、連続したデータ領域を探すのみで、その時点ではファイルへの割り当てを行わず、代わりにそれを検索開始ポイントとしてファイル システム オブジェクトにセットします。これにより、そのボリューム上で別の操作(FAT変更を伴う)が行われない限り、書き込まれるファイルは少なくともそのサイズまでは連続性が保証され、遅延無く書き込めることになります。

時間的制約のあるファイル読み書き操作において、連続データ領域を割り当てられたファイルは有利となります。これは、分割されたファイルによりもたらされる無用なランダム アクセスが減ることにより、ファイル システムやストレージ デバイスの処理のオーバーヘッドが削減されるからです。特にexFATボリューム上の連続ファイルでは一切のFATアクセスが発生せず、効率的なシーケンシャル アクセスが行えます。

連続ファイルに対して低レベルI/Oを使用したさらに効率的な直接アクセスも容易に行えますが、これは将来の互換性の点で推奨はされません。

#### 対応情報

`_USE_EXPAND == 1`で、かつ`_FS_READONLY == 0`のとき使用可能です。

#### 使用例

        /* 連続ファイルの作成 */

        /* 新しいファイルの作成 */
        res = f_open(fp = malloc(sizeof (FIL)), "file.dat", FA_WRITE|FA_CREATE_ALWAYS);
        if (res) { /* ファイルが開かれたかチェック */
            free(fp);
            die("Failed to open the file.");
        }

        /* 100 MiB の連続領域を割り当てる */
        res = f_expand(fp, 104857600, 1);
        if (res) { /* 割り当てられたかチェック */
            f_close(fp);
            free(fp);
            die("Failed to allocate contiguous area.");
        }
        /* 連続ファイル作成成功 fp でアクセス可能 */

        /* ファイル システムを介さず直接アクセスする例 */

        /* ファイル データの物理的位置を取得 */
        drv = fp->obj.fs->drv;
        sect = fp->obj.fs->database + fp->obj.fs->csize * (fp->obj.sclust - 2);

        /* ファイル先頭から2048セクタを書き込み */
        res = disk_write(drv, buffer, sect, 2048);

#### 参照

`f_open, f_lseek, FIL`

戻る